Coverage Report


Files: 191
Lines: 45000
Covered: 1124 / 8507 (13.2%)


Lines covered: 0 / 38 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.15;
3

                            
                        
4
import "forge-std/console2.sol";
5
import {Script} from "forge-std/Script.sol";
6
import {UintString} from "./utils/UintString.sol";
7

                            
                        
8
contract GasSnapshot is Script {
9
    error GasMismatch(uint256 oldGas, uint256 newGas);
10

                            
                        
11
    /// @notice if this environment variable is true, we revert on gas mismatch
12
    string public constant CHECK_ENV_VAR = "FORGE_SNAPSHOT_CHECK";
13
    /// @notice save gas snapshots in this dir
14
    string public constant SNAP_DIR = ".forge-snapshots/";
15
    /// @notice gas overhead for the snapshotting function itself
16
    uint256 private constant GAS_CALIBRATION = 100;
17

                            
                        
18
    /// @notice if true, revert on gas mismatch, else overwrite with new values
19
    bool internal check;
20
    /// @notice Transient variable for the start gas
21
    uint256 private cachedGas;
22
    /// @notice Transient variable for the snapshot name
23
    string private cachedName;
24

                            
                        
25
    constructor() {
26
        _mkdirp(SNAP_DIR);
27
        //try vm.envBool(CHECK_ENV_VAR) returns (bool _check) {
28
        //    check = _check;
29
        //} catch {
30
        //    check = false;
31
        //}
32
    }
33

                            
                        
34
    /// @notice Write a size snapshot with the given name
35
    /// @param target the contract to snapshot the size of
36
    /// @dev The next call to `snapEnd` will end the snapshot
37
    function snapSize(string memory name, address target) internal {
38
        uint256 size = target.code.length;
39
        if (check) {
40
            _checkSnapshot(name, size);
41
        } else {
42
            _writeSnapshot(name, size);
43
        }
44
    }
45

                            
                        
46
    /// @notice Snapshot the given value
47
    function snap(string memory name, uint256 value) internal {
48
        if (check) {
49
            _checkSnapshot(name, value);
50
        } else {
51
            _writeSnapshot(name, value);
52
        }
53
    }
54

                            
                        
55
    /// @notice Snapshot the given external closure
56
    function snap(string memory name, function() external fn) internal {
57
        uint256 gasBefore = gasleft();
58
        fn();
59
        uint256 gasUsed = gasBefore - gasleft();
60
        if (check) {
61
            _checkSnapshot(name, gasUsed);
62
        } else {
63
            _writeSnapshot(name, gasUsed);
64
        }
65
    }
66

                            
                        
67
    /// @notice Snapshot the given internal closure
68
    function snap(string memory name, function() internal fn) internal {
69
        uint256 gasBefore = gasleft();
70
        fn();
71
        uint256 gasUsed = gasBefore - gasleft();
72
        if (check) {
73
            _checkSnapshot(name, gasUsed);
74
        } else {
75
            _writeSnapshot(name, gasUsed);
76
        }
77
    }
78

                            
                        
79
    /// @notice Snapshot using forge isolate of gas of the previous call
80
    /// @dev most accurate as this uses a complete transaction and no storage semantics
81
    function snapLastCall(string memory name) internal {
82
        uint256 gasUsed = vm.lastCallGas().gasTotalUsed;
83
        if (check) {
84
            _checkSnapshot(name, gasUsed);
85
        } else {
86
            _writeSnapshot(name, gasUsed);
87
        }
88
    }
89

                            
                        
90
    /// @notice Start a snapshot with the given name
91
    /// @dev The next call to `snapEnd` will end the snapshot
92
    function snapStart(string memory name) internal {
93
        // warm up cachedGas so the only sstore after calling `gasleft` is exactly 100 gas
94
        cachedGas = 1;
95
        cachedName = name;
96
        cachedGas = gasleft();
97
    }
98

                            
                        
99
    /// @notice End the current snapshot
100
    /// @dev Must be called after a call to `snapStart`, else reverts with underflow
101
    function snapEnd() internal {
102
        uint256 newGasLeft = gasleft();
103
        // subtract original gas and snapshot gas overhead
104
        uint256 gasUsed = cachedGas - newGasLeft - GAS_CALIBRATION;
105
        // reset to 0 so all writes for consistent overhead handling
106
        cachedGas = 0;
107

                            
                        
108
        if (check) {
109
            _checkSnapshot(cachedName, gasUsed);
110
        } else {
111
            _writeSnapshot(cachedName, gasUsed);
112
        }
113
    }
114

                            
                        
115
    /// @notice Check the gas usage against the snapshot. Revert on mismatch
116
    function _checkSnapshot(string memory name, uint256 gasUsed) internal view {
117
        uint256 oldGasUsed = _readSnapshot(name);
118
        if (oldGasUsed != gasUsed) {
119
            revert GasMismatch(oldGasUsed, gasUsed);
120
        }
121
    }
122

                            
                        
123
    /// @notice Read the last snapshot value from the file
124
    function _readSnapshot(string memory name) private view returns (uint256 res) {
125
        string memory oldValue = vm.readLine(_getSnapFile(name));
126
        res = UintString.stringToUint(oldValue);
127
    }
128

                            
                        
129
    /// @notice Write the new snapshot value to file
130
    function _writeSnapshot(string memory name, uint256 gasUsed) private {
131
        vm.writeFile(_getSnapFile(name), vm.toString(gasUsed));
132
    }
133

                            
                        
134
    /// @notice Make the directory for snapshots
135
    function _mkdirp(string memory dir) private {
136
        string[] memory mkdirp = new string[](3);
137
        mkdirp[0] = "mkdir";
138
        mkdirp[1] = "-p";
139
        mkdirp[2] = dir;
140
        vm.ffi(mkdirp);
141
    }
142

                            
                        
143
    /// @notice Get the snapshot file name
144
    function _getSnapFile(string memory name) private pure returns (string memory) {
145
        return string(abi.encodePacked(SNAP_DIR, name, ".snap"));
146
    }
147

                            
                        
148
    /// @notice sets the library to check mode
149
    function setCheckMode(bool _check) internal {
150
        check = _check;
151
    }
152
}
153

                            
                        

Lines covered: 0 / 11 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.15;
3

                            
                        
4
library UintString {
5
    error InvalidStringNumber(string s);
6

                            
                        
7
    /// @notice converts the given string s into a uint256
8
    function stringToUint(string memory s) internal pure returns (uint256 result) {
9
        bytes memory b = bytes(s);
10
        uint256 oldResult;
11
        for (uint256 i; i < b.length;) {
12
            // c = b[i] was not needed
13
            if (uint8(b[i]) >= 48 && uint8(b[i]) <= 57) {
14
                // store old value so we can check for overflows
15
                oldResult = result;
16
                result = result * 10 + (uint8(b[i]) - 48);
17
                if (oldResult > result) {
18
                    // we can only get here if the result overflowed and is smaller than last stored value
19
                    revert InvalidStringNumber(s);
20
                }
21
            } else {
22
                revert InvalidStringNumber(s);
23
            }
24
            unchecked {
25
                ++i;
26
            }
27
        }
28
    }
29
}
30

                            
                        

Lines covered: 0 / 1 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
import {StdStorage} from "./StdStorage.sol";
5
import {Vm, VmSafe} from "./Vm.sol";
6

                            
                        
7
abstract contract CommonBase {
8
    // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.
9
    address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
10
    // console.sol and console2.sol work by executing a staticcall to this address.
11
    address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
12
    // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
13
    address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
14
    // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.
15
    address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller"))));
16
    // Address of the test contract, deployed by the DEFAULT_SENDER.
17
    address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
18
    // Deterministic deployment address of the Multicall3 contract.
19
    address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;
20
    // The order of the secp256k1 curve.
21
    uint256 internal constant SECP256K1_ORDER =
22
        115792089237316195423570985008687907852837564279074904382605163141518161494337;
23

                            
                        
24
    uint256 internal constant UINT256_MAX =
25
        115792089237316195423570985008687907853269984665640564039457584007913129639935;
26

                            
                        
27
    Vm internal constant vm = Vm(VM_ADDRESS);
28
    StdStorage internal stdstore;
29
}
30

                            
                        
31
abstract contract TestBase is CommonBase {}
32

                            
                        
33
abstract contract ScriptBase is CommonBase {
34
    VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);
35
}
36

                            
                        

Lines covered: 0 / 1 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
// 💬 ABOUT
5
// Forge Std's default Script.
6

                            
                        
7
// 🧩 MODULES
8
import {console} from "./console.sol";
9
import {console2} from "./console2.sol";
10
import {safeconsole} from "./safeconsole.sol";
11
import {StdChains} from "./StdChains.sol";
12
import {StdCheatsSafe} from "./StdCheats.sol";
13
import {stdJson} from "./StdJson.sol";
14
import {stdMath} from "./StdMath.sol";
15
import {StdStorage, stdStorageSafe} from "./StdStorage.sol";
16
import {StdStyle} from "./StdStyle.sol";
17
import {StdUtils} from "./StdUtils.sol";
18
import {VmSafe} from "./Vm.sol";
19

                            
                        
20
// 📦 BOILERPLATE
21
import {ScriptBase} from "./Base.sol";
22

                            
                        
23
// ⭐️ SCRIPT
24
abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils {
25
    // Note: IS_SCRIPT() must return true.
26
    bool public IS_SCRIPT = true;
27
}
28

                            
                        

Lines covered: 0 / 31 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3
pragma experimental ABIEncoderV2;
4

                            
                        
5
import {Vm} from "./Vm.sol";
6

                            
                        
7
abstract contract StdAssertions {
8
    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
9

                            
                        
10
    event log(string);
11
    event logs(bytes);
12

                            
                        
13
    event log_address(address);
14
    event log_bytes32(bytes32);
15
    event log_int(int256);
16
    event log_uint(uint256);
17
    event log_bytes(bytes);
18
    event log_string(string);
19

                            
                        
20
    event log_named_address(string key, address val);
21
    event log_named_bytes32(string key, bytes32 val);
22
    event log_named_decimal_int(string key, int256 val, uint256 decimals);
23
    event log_named_decimal_uint(string key, uint256 val, uint256 decimals);
24
    event log_named_int(string key, int256 val);
25
    event log_named_uint(string key, uint256 val);
26
    event log_named_bytes(string key, bytes val);
27
    event log_named_string(string key, string val);
28

                            
                        
29
    event log_array(uint256[] val);
30
    event log_array(int256[] val);
31
    event log_array(address[] val);
32
    event log_named_array(string key, uint256[] val);
33
    event log_named_array(string key, int256[] val);
34
    event log_named_array(string key, address[] val);
35

                            
                        
36
    bool private _failed;
37

                            
                        
38
    function failed() public view returns (bool) {
39
        if (_failed) {
40
            return _failed;
41
        } else {
42
            return vm.load(address(vm), bytes32("failed")) != bytes32(0);
43
        }
44
    }
45

                            
                        
46
    function fail() internal virtual {
47
        vm.store(address(vm), bytes32("failed"), bytes32(uint256(1)));
48
        _failed = true;
49
    }
50

                            
                        
51
    function assertTrue(bool data) internal pure virtual {
52
        vm.assertTrue(data);
53
    }
54

                            
                        
55
    function assertTrue(bool data, string memory err) internal pure virtual {
56
        vm.assertTrue(data, err);
57
    }
58

                            
                        
59
    function assertFalse(bool data) internal pure virtual {
60
        vm.assertFalse(data);
61
    }
62

                            
                        
63
    function assertFalse(bool data, string memory err) internal pure virtual {
64
        vm.assertFalse(data, err);
65
    }
66

                            
                        
67
    function assertEq(bool left, bool right) internal pure virtual {
68
        vm.assertEq(left, right);
69
    }
70

                            
                        
71
    function assertEq(bool left, bool right, string memory err) internal pure virtual {
72
        vm.assertEq(left, right, err);
73
    }
74

                            
                        
75
    function assertEq(uint256 left, uint256 right) internal pure virtual {
76
        vm.assertEq(left, right);
77
    }
78

                            
                        
79
    function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual {
80
        vm.assertEq(left, right, err);
81
    }
82

                            
                        
83
    function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
84
        vm.assertEqDecimal(left, right, decimals);
85
    }
86

                            
                        
87
    function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
88
        vm.assertEqDecimal(left, right, decimals, err);
89
    }
90

                            
                        
91
    function assertEq(int256 left, int256 right) internal pure virtual {
92
        vm.assertEq(left, right);
93
    }
94

                            
                        
95
    function assertEq(int256 left, int256 right, string memory err) internal pure virtual {
96
        vm.assertEq(left, right, err);
97
    }
98

                            
                        
99
    function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
100
        vm.assertEqDecimal(left, right, decimals);
101
    }
102

                            
                        
103
    function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
104
        vm.assertEqDecimal(left, right, decimals, err);
105
    }
106

                            
                        
107
    function assertEq(address left, address right) internal pure virtual {
108
        vm.assertEq(left, right);
109
    }
110

                            
                        
111
    function assertEq(address left, address right, string memory err) internal pure virtual {
112
        vm.assertEq(left, right, err);
113
    }
114

                            
                        
115
    function assertEq(bytes32 left, bytes32 right) internal pure virtual {
116
        vm.assertEq(left, right);
117
    }
118

                            
                        
119
    function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
120
        vm.assertEq(left, right, err);
121
    }
122

                            
                        
123
    function assertEq32(bytes32 left, bytes32 right) internal pure virtual {
124
        assertEq(left, right);
125
    }
126

                            
                        
127
    function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
128
        assertEq(left, right, err);
129
    }
130

                            
                        
131
    function assertEq(string memory left, string memory right) internal pure virtual {
132
        vm.assertEq(left, right);
133
    }
134

                            
                        
135
    function assertEq(string memory left, string memory right, string memory err) internal pure virtual {
136
        vm.assertEq(left, right, err);
137
    }
138

                            
                        
139
    function assertEq(bytes memory left, bytes memory right) internal pure virtual {
140
        vm.assertEq(left, right);
141
    }
142

                            
                        
143
    function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
144
        vm.assertEq(left, right, err);
145
    }
146

                            
                        
147
    function assertEq(bool[] memory left, bool[] memory right) internal pure virtual {
148
        vm.assertEq(left, right);
149
    }
150

                            
                        
151
    function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
152
        vm.assertEq(left, right, err);
153
    }
154

                            
                        
155
    function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
156
        vm.assertEq(left, right);
157
    }
158

                            
                        
159
    function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
160
        vm.assertEq(left, right, err);
161
    }
162

                            
                        
163
    function assertEq(int256[] memory left, int256[] memory right) internal pure virtual {
164
        vm.assertEq(left, right);
165
    }
166

                            
                        
167
    function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
168
        vm.assertEq(left, right, err);
169
    }
170

                            
                        
171
    function assertEq(address[] memory left, address[] memory right) internal pure virtual {
172
        vm.assertEq(left, right);
173
    }
174

                            
                        
175
    function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
176
        vm.assertEq(left, right, err);
177
    }
178

                            
                        
179
    function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
180
        vm.assertEq(left, right);
181
    }
182

                            
                        
183
    function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
184
        vm.assertEq(left, right, err);
185
    }
186

                            
                        
187
    function assertEq(string[] memory left, string[] memory right) internal pure virtual {
188
        vm.assertEq(left, right);
189
    }
190

                            
                        
191
    function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
192
        vm.assertEq(left, right, err);
193
    }
194

                            
                        
195
    function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
196
        vm.assertEq(left, right);
197
    }
198

                            
                        
199
    function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
200
        vm.assertEq(left, right, err);
201
    }
202

                            
                        
203
    // Legacy helper
204
    function assertEqUint(uint256 left, uint256 right) internal pure virtual {
205
        assertEq(left, right);
206
    }
207

                            
                        
208
    function assertNotEq(bool left, bool right) internal pure virtual {
209
        vm.assertNotEq(left, right);
210
    }
211

                            
                        
212
    function assertNotEq(bool left, bool right, string memory err) internal pure virtual {
213
        vm.assertNotEq(left, right, err);
214
    }
215

                            
                        
216
    function assertNotEq(uint256 left, uint256 right) internal pure virtual {
217
        vm.assertNotEq(left, right);
218
    }
219

                            
                        
220
    function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual {
221
        vm.assertNotEq(left, right, err);
222
    }
223

                            
                        
224
    function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
225
        vm.assertNotEqDecimal(left, right, decimals);
226
    }
227

                            
                        
228
    function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err)
229
        internal
230
        pure
231
        virtual
232
    {
233
        vm.assertNotEqDecimal(left, right, decimals, err);
234
    }
235

                            
                        
236
    function assertNotEq(int256 left, int256 right) internal pure virtual {
237
        vm.assertNotEq(left, right);
238
    }
239

                            
                        
240
    function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual {
241
        vm.assertNotEq(left, right, err);
242
    }
243

                            
                        
244
    function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
245
        vm.assertNotEqDecimal(left, right, decimals);
246
    }
247

                            
                        
248
    function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
249
        vm.assertNotEqDecimal(left, right, decimals, err);
250
    }
251

                            
                        
252
    function assertNotEq(address left, address right) internal pure virtual {
253
        vm.assertNotEq(left, right);
254
    }
255

                            
                        
256
    function assertNotEq(address left, address right, string memory err) internal pure virtual {
257
        vm.assertNotEq(left, right, err);
258
    }
259

                            
                        
260
    function assertNotEq(bytes32 left, bytes32 right) internal pure virtual {
261
        vm.assertNotEq(left, right);
262
    }
263

                            
                        
264
    function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
265
        vm.assertNotEq(left, right, err);
266
    }
267

                            
                        
268
    function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual {
269
        assertNotEq(left, right);
270
    }
271

                            
                        
272
    function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
273
        assertNotEq(left, right, err);
274
    }
275

                            
                        
276
    function assertNotEq(string memory left, string memory right) internal pure virtual {
277
        vm.assertNotEq(left, right);
278
    }
279

                            
                        
280
    function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual {
281
        vm.assertNotEq(left, right, err);
282
    }
283

                            
                        
284
    function assertNotEq(bytes memory left, bytes memory right) internal pure virtual {
285
        vm.assertNotEq(left, right);
286
    }
287

                            
                        
288
    function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
289
        vm.assertNotEq(left, right, err);
290
    }
291

                            
                        
292
    function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual {
293
        vm.assertNotEq(left, right);
294
    }
295

                            
                        
296
    function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
297
        vm.assertNotEq(left, right, err);
298
    }
299

                            
                        
300
    function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
301
        vm.assertNotEq(left, right);
302
    }
303

                            
                        
304
    function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
305
        vm.assertNotEq(left, right, err);
306
    }
307

                            
                        
308
    function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual {
309
        vm.assertNotEq(left, right);
310
    }
311

                            
                        
312
    function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
313
        vm.assertNotEq(left, right, err);
314
    }
315

                            
                        
316
    function assertNotEq(address[] memory left, address[] memory right) internal pure virtual {
317
        vm.assertNotEq(left, right);
318
    }
319

                            
                        
320
    function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
321
        vm.assertNotEq(left, right, err);
322
    }
323

                            
                        
324
    function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
325
        vm.assertNotEq(left, right);
326
    }
327

                            
                        
328
    function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
329
        vm.assertNotEq(left, right, err);
330
    }
331

                            
                        
332
    function assertNotEq(string[] memory left, string[] memory right) internal pure virtual {
333
        vm.assertNotEq(left, right);
334
    }
335

                            
                        
336
    function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
337
        vm.assertNotEq(left, right, err);
338
    }
339

                            
                        
340
    function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
341
        vm.assertNotEq(left, right);
342
    }
343

                            
                        
344
    function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
345
        vm.assertNotEq(left, right, err);
346
    }
347

                            
                        
348
    function assertLt(uint256 left, uint256 right) internal pure virtual {
349
        vm.assertLt(left, right);
350
    }
351

                            
                        
352
    function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual {
353
        vm.assertLt(left, right, err);
354
    }
355

                            
                        
356
    function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
357
        vm.assertLtDecimal(left, right, decimals);
358
    }
359

                            
                        
360
    function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
361
        vm.assertLtDecimal(left, right, decimals, err);
362
    }
363

                            
                        
364
    function assertLt(int256 left, int256 right) internal pure virtual {
365
        vm.assertLt(left, right);
366
    }
367

                            
                        
368
    function assertLt(int256 left, int256 right, string memory err) internal pure virtual {
369
        vm.assertLt(left, right, err);
370
    }
371

                            
                        
372
    function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
373
        vm.assertLtDecimal(left, right, decimals);
374
    }
375

                            
                        
376
    function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
377
        vm.assertLtDecimal(left, right, decimals, err);
378
    }
379

                            
                        
380
    function assertGt(uint256 left, uint256 right) internal pure virtual {
381
        vm.assertGt(left, right);
382
    }
383

                            
                        
384
    function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual {
385
        vm.assertGt(left, right, err);
386
    }
387

                            
                        
388
    function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
389
        vm.assertGtDecimal(left, right, decimals);
390
    }
391

                            
                        
392
    function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
393
        vm.assertGtDecimal(left, right, decimals, err);
394
    }
395

                            
                        
396
    function assertGt(int256 left, int256 right) internal pure virtual {
397
        vm.assertGt(left, right);
398
    }
399

                            
                        
400
    function assertGt(int256 left, int256 right, string memory err) internal pure virtual {
401
        vm.assertGt(left, right, err);
402
    }
403

                            
                        
404
    function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
405
        vm.assertGtDecimal(left, right, decimals);
406
    }
407

                            
                        
408
    function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
409
        vm.assertGtDecimal(left, right, decimals, err);
410
    }
411

                            
                        
412
    function assertLe(uint256 left, uint256 right) internal pure virtual {
413
        vm.assertLe(left, right);
414
    }
415

                            
                        
416
    function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual {
417
        vm.assertLe(left, right, err);
418
    }
419

                            
                        
420
    function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
421
        vm.assertLeDecimal(left, right, decimals);
422
    }
423

                            
                        
424
    function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
425
        vm.assertLeDecimal(left, right, decimals, err);
426
    }
427

                            
                        
428
    function assertLe(int256 left, int256 right) internal pure virtual {
429
        vm.assertLe(left, right);
430
    }
431

                            
                        
432
    function assertLe(int256 left, int256 right, string memory err) internal pure virtual {
433
        vm.assertLe(left, right, err);
434
    }
435

                            
                        
436
    function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
437
        vm.assertLeDecimal(left, right, decimals);
438
    }
439

                            
                        
440
    function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
441
        vm.assertLeDecimal(left, right, decimals, err);
442
    }
443

                            
                        
444
    function assertGe(uint256 left, uint256 right) internal pure virtual {
445
        vm.assertGe(left, right);
446
    }
447

                            
                        
448
    function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual {
449
        vm.assertGe(left, right, err);
450
    }
451

                            
                        
452
    function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
453
        vm.assertGeDecimal(left, right, decimals);
454
    }
455

                            
                        
456
    function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
457
        vm.assertGeDecimal(left, right, decimals, err);
458
    }
459

                            
                        
460
    function assertGe(int256 left, int256 right) internal pure virtual {
461
        vm.assertGe(left, right);
462
    }
463

                            
                        
464
    function assertGe(int256 left, int256 right, string memory err) internal pure virtual {
465
        vm.assertGe(left, right, err);
466
    }
467

                            
                        
468
    function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
469
        vm.assertGeDecimal(left, right, decimals);
470
    }
471

                            
                        
472
    function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
473
        vm.assertGeDecimal(left, right, decimals, err);
474
    }
475

                            
                        
476
    function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual {
477
        vm.assertApproxEqAbs(left, right, maxDelta);
478
    }
479

                            
                        
480
    function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err)
481
        internal
482
        pure
483
        virtual
484
    {
485
        vm.assertApproxEqAbs(left, right, maxDelta, err);
486
    }
487

                            
                        
488
    function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals)
489
        internal
490
        pure
491
        virtual
492
    {
493
        vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals);
494
    }
495

                            
                        
496
    function assertApproxEqAbsDecimal(
497
        uint256 left,
498
        uint256 right,
499
        uint256 maxDelta,
500
        uint256 decimals,
501
        string memory err
502
    ) internal pure virtual {
503
        vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err);
504
    }
505

                            
                        
506
    function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual {
507
        vm.assertApproxEqAbs(left, right, maxDelta);
508
    }
509

                            
                        
510
    function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual {
511
        vm.assertApproxEqAbs(left, right, maxDelta, err);
512
    }
513

                            
                        
514
    function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals)
515
        internal
516
        pure
517
        virtual
518
    {
519
        vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals);
520
    }
521

                            
                        
522
    function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err)
523
        internal
524
        pure
525
        virtual
526
    {
527
        vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err);
528
    }
529

                            
                        
530
    function assertApproxEqRel(
531
        uint256 left,
532
        uint256 right,
533
        uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%
534
    ) internal pure virtual {
535
        vm.assertApproxEqRel(left, right, maxPercentDelta);
536
    }
537

                            
                        
538
    function assertApproxEqRel(
539
        uint256 left,
540
        uint256 right,
541
        uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
542
        string memory err
543
    ) internal pure virtual {
544
        vm.assertApproxEqRel(left, right, maxPercentDelta, err);
545
    }
546

                            
                        
547
    function assertApproxEqRelDecimal(
548
        uint256 left,
549
        uint256 right,
550
        uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
551
        uint256 decimals
552
    ) internal pure virtual {
553
        vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals);
554
    }
555

                            
                        
556
    function assertApproxEqRelDecimal(
557
        uint256 left,
558
        uint256 right,
559
        uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
560
        uint256 decimals,
561
        string memory err
562
    ) internal pure virtual {
563
        vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err);
564
    }
565

                            
                        
566
    function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual {
567
        vm.assertApproxEqRel(left, right, maxPercentDelta);
568
    }
569

                            
                        
570
    function assertApproxEqRel(
571
        int256 left,
572
        int256 right,
573
        uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
574
        string memory err
575
    ) internal pure virtual {
576
        vm.assertApproxEqRel(left, right, maxPercentDelta, err);
577
    }
578

                            
                        
579
    function assertApproxEqRelDecimal(
580
        int256 left,
581
        int256 right,
582
        uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
583
        uint256 decimals
584
    ) internal pure virtual {
585
        vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals);
586
    }
587

                            
                        
588
    function assertApproxEqRelDecimal(
589
        int256 left,
590
        int256 right,
591
        uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
592
        uint256 decimals,
593
        string memory err
594
    ) internal pure virtual {
595
        vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err);
596
    }
597

                            
                        
598
    // Inherited from DSTest, not used but kept for backwards-compatibility
599
    function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) {
600
        return keccak256(left) == keccak256(right);
601
    }
602

                            
                        
603
    function assertEq0(bytes memory left, bytes memory right) internal pure virtual {
604
        assertEq(left, right);
605
    }
606

                            
                        
607
    function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
608
        assertEq(left, right, err);
609
    }
610

                            
                        
611
    function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual {
612
        assertNotEq(left, right);
613
    }
614

                            
                        
615
    function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
616
        assertNotEq(left, right, err);
617
    }
618

                            
                        
619
    function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {
620
        assertEqCall(target, callDataA, target, callDataB, true);
621
    }
622

                            
                        
623
    function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)
624
        internal
625
        virtual
626
    {
627
        assertEqCall(targetA, callDataA, targetB, callDataB, true);
628
    }
629

                            
                        
630
    function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)
631
        internal
632
        virtual
633
    {
634
        assertEqCall(target, callDataA, target, callDataB, strictRevertData);
635
    }
636

                            
                        
637
    function assertEqCall(
638
        address targetA,
639
        bytes memory callDataA,
640
        address targetB,
641
        bytes memory callDataB,
642
        bool strictRevertData
643
    ) internal virtual {
644
        (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);
645
        (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);
646

                            
                        
647
        if (successA && successB) {
648
            assertEq(returnDataA, returnDataB, "Call return data does not match");
649
        }
650

                            
                        
651
        if (!successA && !successB && strictRevertData) {
652
            assertEq(returnDataA, returnDataB, "Call revert data does not match");
653
        }
654

                            
                        
655
        if (!successA && successB) {
656
            emit log("Error: Calls were not equal");
657
            emit log_named_bytes("  Left call revert data", returnDataA);
658
            emit log_named_bytes(" Right call return data", returnDataB);
659
            revert("assertion failed");
660
        }
661

                            
                        
662
        if (successA && !successB) {
663
            emit log("Error: Calls were not equal");
664
            emit log_named_bytes("  Left call return data", returnDataA);
665
            emit log_named_bytes(" Right call revert data", returnDataB);
666
            revert("assertion failed");
667
        }
668
    }
669
}
670

                            
                        

Lines covered: 1 / 1 (100.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
import {VmSafe} from "./Vm.sol";
5

                            
                        
6
/**
7
 * StdChains provides information about EVM compatible chains that can be used in scripts/tests.
8
 * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are
9
 * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of
10
 * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the
11
 * alias used in this contract, which can be found as the first argument to the
12
 * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function.
13
 *
14
 * There are two main ways to use this contract:
15
 *   1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or
16
 *      `setChain(string memory chainAlias, Chain memory chain)`
17
 *   2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.
18
 *
19
 * The first time either of those are used, chains are initialized with the default set of RPC URLs.
20
 * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in
21
 * `defaultRpcUrls`.
22
 *
23
 * The `setChain` function is straightforward, and it simply saves off the given chain data.
24
 *
25
 * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say
26
 * we want to retrieve the RPC URL for `mainnet`:
27
 *   - If you have specified data with `setChain`, it will return that.
28
 *   - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it
29
 *     is valid (e.g. a URL is specified, or an environment variable is given and exists).
30
 *   - If neither of the above conditions is met, the default data is returned.
31
 *
32
 * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.
33
 */
34
abstract contract StdChains {
35
    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
36

                            
                        
37
    bool private stdChainsInitialized;
38

                            
                        
39
    struct ChainData {
40
        string name;
41
        uint256 chainId;
42
        string rpcUrl;
43
    }
44

                            
                        
45
    struct Chain {
46
        // The chain name.
47
        string name;
48
        // The chain's Chain ID.
49
        uint256 chainId;
50
        // The chain's alias. (i.e. what gets specified in `foundry.toml`).
51
        string chainAlias;
52
        // A default RPC endpoint for this chain.
53
        // NOTE: This default RPC URL is included for convenience to facilitate quick tests and
54
        // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy
55
        // usage as you will be throttled and this is a disservice to others who need this endpoint.
56
        string rpcUrl;
57
    }
58

                            
                        
59
    // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.
60
    mapping(string => Chain) private chains;
61
    // Maps from the chain's alias to it's default RPC URL.
62
    mapping(string => string) private defaultRpcUrls;
63
    // Maps from a chain ID to it's alias.
64
    mapping(uint256 => string) private idToAlias;
65

                            
                        
66
√ 3
    bool private fallbackToDefaultRpcUrls = true;
67

                            
                        
68
    // The RPC URL will be fetched from config or defaultRpcUrls if possible.
69
    function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {
70
        require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string.");
71

                            
                        
72
        initializeStdChains();
73
        chain = chains[chainAlias];
74
        require(
75
            chain.chainId != 0,
76
            string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found."))
77
        );
78

                            
                        
79
        chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
80
    }
81

                            
                        
82
    function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {
83
        require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0.");
84
        initializeStdChains();
85
        string memory chainAlias = idToAlias[chainId];
86

                            
                        
87
        chain = chains[chainAlias];
88

                            
                        
89
        require(
90
            chain.chainId != 0,
91
            string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found."))
92
        );
93

                            
                        
94
        chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
95
    }
96

                            
                        
97
    // set chain info, with priority to argument's rpcUrl field.
98
    function setChain(string memory chainAlias, ChainData memory chain) internal virtual {
99
        require(
100
            bytes(chainAlias).length != 0,
101
            "StdChains setChain(string,ChainData): Chain alias cannot be the empty string."
102
        );
103

                            
                        
104
        require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0.");
105

                            
                        
106
        initializeStdChains();
107
        string memory foundAlias = idToAlias[chain.chainId];
108

                            
                        
109
        require(
110
            bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),
111
            string(
112
                abi.encodePacked(
113
                    "StdChains setChain(string,ChainData): Chain ID ",
114
                    vm.toString(chain.chainId),
115
                    " already used by \"",
116
                    foundAlias,
117
                    "\"."
118
                )
119
            )
120
        );
121

                            
                        
122
        uint256 oldChainId = chains[chainAlias].chainId;
123
        delete idToAlias[oldChainId];
124

                            
                        
125
        chains[chainAlias] =
126
            Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});
127
        idToAlias[chain.chainId] = chainAlias;
128
    }
129

                            
                        
130
    // set chain info, with priority to argument's rpcUrl field.
131
    function setChain(string memory chainAlias, Chain memory chain) internal virtual {
132
        setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
133
    }
134

                            
                        
135
    function _toUpper(string memory str) private pure returns (string memory) {
136
        bytes memory strb = bytes(str);
137
        bytes memory copy = new bytes(strb.length);
138
        for (uint256 i = 0; i < strb.length; i++) {
139
            bytes1 b = strb[i];
140
            if (b >= 0x61 && b <= 0x7A) {
141
                copy[i] = bytes1(uint8(b) - 32);
142
            } else {
143
                copy[i] = b;
144
            }
145
        }
146
        return string(copy);
147
    }
148

                            
                        
149
    // lookup rpcUrl, in descending order of priority:
150
    // current -> config (foundry.toml) -> environment variable -> default
151
    function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain)
152
        private
153
        view
154
        returns (Chain memory)
155
    {
156
        if (bytes(chain.rpcUrl).length == 0) {
157
            try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {
158
                chain.rpcUrl = configRpcUrl;
159
            } catch (bytes memory err) {
160
                string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL"));
161
                if (fallbackToDefaultRpcUrls) {
162
                    chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);
163
                } else {
164
                    chain.rpcUrl = vm.envString(envName);
165
                }
166
                // Distinguish 'not found' from 'cannot read'
167
                // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions
168
                bytes memory oldNotFoundError =
169
                    abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias)));
170
                bytes memory newNotFoundError = abi.encodeWithSignature(
171
                    "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias))
172
                );
173
                bytes32 errHash = keccak256(err);
174
                if (
175
                    (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError))
176
                        || bytes(chain.rpcUrl).length == 0
177
                ) {
178
                    /// @solidity memory-safe-assembly
179
                    assembly {
180
                        revert(add(32, err), mload(err))
181
                    }
182
                }
183
            }
184
        }
185
        return chain;
186
    }
187

                            
                        
188
    function setFallbackToDefaultRpcUrls(bool useDefault) internal {
189
        fallbackToDefaultRpcUrls = useDefault;
190
    }
191

                            
                        
192
    function initializeStdChains() private {
193
        if (stdChainsInitialized) return;
194

                            
                        
195
        stdChainsInitialized = true;
196

                            
                        
197
        // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol`
198
        setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545"));
199
        setChainWithDefaultRpcUrl(
200
            "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP")
201
        );
202
        setChainWithDefaultRpcUrl(
203
            "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
204
        );
205
        setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io"));
206
        setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
207
        setChainWithDefaultRpcUrl(
208
            "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io")
209
        );
210
        setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
211
        setChainWithDefaultRpcUrl(
212
            "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc")
213
        );
214
        setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc"));
215
        setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com"));
216
        setChainWithDefaultRpcUrl(
217
            "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology")
218
        );
219
        setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc"));
220
        setChainWithDefaultRpcUrl(
221
            "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc")
222
        );
223
        setChainWithDefaultRpcUrl(
224
            "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org")
225
        );
226
        setChainWithDefaultRpcUrl(
227
            "bnb_smart_chain_testnet",
228
            ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel")
229
        );
230
        setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com"));
231
        setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network"));
232
        setChainWithDefaultRpcUrl(
233
            "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network")
234
        );
235
        setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network"));
236
        setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org"));
237
        setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
238
        setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io"));
239
        setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io"));
240
        setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/"));
241
        setChainWithDefaultRpcUrl(
242
            "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/")
243
        );
244
        setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com"));
245
        setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com"));
246
        setChainWithDefaultRpcUrl(
247
            "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com")
248
        );
249
    }
250

                            
                        
251
    // set chain info, with priority to chainAlias' rpc url in foundry.toml
252
    function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {
253
        string memory rpcUrl = chain.rpcUrl;
254
        defaultRpcUrls[chainAlias] = rpcUrl;
255
        chain.rpcUrl = "";
256
        setChain(chainAlias, chain);
257
        chain.rpcUrl = rpcUrl; // restore argument
258
    }
259
}
260

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
pragma experimental ABIEncoderV2;
5

                            
                        
6
import {StdStorage, stdStorage} from "./StdStorage.sol";
7
import {console2} from "./console2.sol";
8
import {Vm} from "./Vm.sol";
9

                            
                        
10
abstract contract StdCheatsSafe {
11
    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
12

                            
                        
13
    uint256 private constant UINT256_MAX =
14
        115792089237316195423570985008687907853269984665640564039457584007913129639935;
15

                            
                        
16
    bool private gasMeteringOff;
17

                            
                        
18
    // Data structures to parse Transaction objects from the broadcast artifact
19
    // that conform to EIP1559. The Raw structs is what is parsed from the JSON
20
    // and then converted to the one that is used by the user for better UX.
21

                            
                        
22
    struct RawTx1559 {
23
        string[] arguments;
24
        address contractAddress;
25
        string contractName;
26
        // json value name = function
27
        string functionSig;
28
        bytes32 hash;
29
        // json value name = tx
30
        RawTx1559Detail txDetail;
31
        // json value name = type
32
        string opcode;
33
    }
34

                            
                        
35
    struct RawTx1559Detail {
36
        AccessList[] accessList;
37
        bytes data;
38
        address from;
39
        bytes gas;
40
        bytes nonce;
41
        address to;
42
        bytes txType;
43
        bytes value;
44
    }
45

                            
                        
46
    struct Tx1559 {
47
        string[] arguments;
48
        address contractAddress;
49
        string contractName;
50
        string functionSig;
51
        bytes32 hash;
52
        Tx1559Detail txDetail;
53
        string opcode;
54
    }
55

                            
                        
56
    struct Tx1559Detail {
57
        AccessList[] accessList;
58
        bytes data;
59
        address from;
60
        uint256 gas;
61
        uint256 nonce;
62
        address to;
63
        uint256 txType;
64
        uint256 value;
65
    }
66

                            
                        
67
    // Data structures to parse Transaction objects from the broadcast artifact
68
    // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
69
    // and then converted to the one that is used by the user for better UX.
70

                            
                        
71
    struct TxLegacy {
72
        string[] arguments;
73
        address contractAddress;
74
        string contractName;
75
        string functionSig;
76
        string hash;
77
        string opcode;
78
        TxDetailLegacy transaction;
79
    }
80

                            
                        
81
    struct TxDetailLegacy {
82
        AccessList[] accessList;
83
        uint256 chainId;
84
        bytes data;
85
        address from;
86
        uint256 gas;
87
        uint256 gasPrice;
88
        bytes32 hash;
89
        uint256 nonce;
90
        bytes1 opcode;
91
        bytes32 r;
92
        bytes32 s;
93
        uint256 txType;
94
        address to;
95
        uint8 v;
96
        uint256 value;
97
    }
98

                            
                        
99
    struct AccessList {
100
        address accessAddress;
101
        bytes32[] storageKeys;
102
    }
103

                            
                        
104
    // Data structures to parse Receipt objects from the broadcast artifact.
105
    // The Raw structs is what is parsed from the JSON
106
    // and then converted to the one that is used by the user for better UX.
107

                            
                        
108
    struct RawReceipt {
109
        bytes32 blockHash;
110
        bytes blockNumber;
111
        address contractAddress;
112
        bytes cumulativeGasUsed;
113
        bytes effectiveGasPrice;
114
        address from;
115
        bytes gasUsed;
116
        RawReceiptLog[] logs;
117
        bytes logsBloom;
118
        bytes status;
119
        address to;
120
        bytes32 transactionHash;
121
        bytes transactionIndex;
122
    }
123

                            
                        
124
    struct Receipt {
125
        bytes32 blockHash;
126
        uint256 blockNumber;
127
        address contractAddress;
128
        uint256 cumulativeGasUsed;
129
        uint256 effectiveGasPrice;
130
        address from;
131
        uint256 gasUsed;
132
        ReceiptLog[] logs;
133
        bytes logsBloom;
134
        uint256 status;
135
        address to;
136
        bytes32 transactionHash;
137
        uint256 transactionIndex;
138
    }
139

                            
                        
140
    // Data structures to parse the entire broadcast artifact, assuming the
141
    // transactions conform to EIP1559.
142

                            
                        
143
    struct EIP1559ScriptArtifact {
144
        string[] libraries;
145
        string path;
146
        string[] pending;
147
        Receipt[] receipts;
148
        uint256 timestamp;
149
        Tx1559[] transactions;
150
        TxReturn[] txReturns;
151
    }
152

                            
                        
153
    struct RawEIP1559ScriptArtifact {
154
        string[] libraries;
155
        string path;
156
        string[] pending;
157
        RawReceipt[] receipts;
158
        TxReturn[] txReturns;
159
        uint256 timestamp;
160
        RawTx1559[] transactions;
161
    }
162

                            
                        
163
    struct RawReceiptLog {
164
        // json value = address
165
        address logAddress;
166
        bytes32 blockHash;
167
        bytes blockNumber;
168
        bytes data;
169
        bytes logIndex;
170
        bool removed;
171
        bytes32[] topics;
172
        bytes32 transactionHash;
173
        bytes transactionIndex;
174
        bytes transactionLogIndex;
175
    }
176

                            
                        
177
    struct ReceiptLog {
178
        // json value = address
179
        address logAddress;
180
        bytes32 blockHash;
181
        uint256 blockNumber;
182
        bytes data;
183
        uint256 logIndex;
184
        bytes32[] topics;
185
        uint256 transactionIndex;
186
        uint256 transactionLogIndex;
187
        bool removed;
188
    }
189

                            
                        
190
    struct TxReturn {
191
        string internalType;
192
        string value;
193
    }
194

                            
                        
195
    struct Account {
196
        address addr;
197
        uint256 key;
198
    }
199

                            
                        
200
    enum AddressType {
201
        Payable,
202
        NonPayable,
203
        ZeroAddress,
204
        Precompile,
205
        ForgeAddress
206
    }
207

                            
                        
208
    // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
209
    function assumeNotBlacklisted(address token, address addr) internal view virtual {
210
        // Nothing to check if `token` is not a contract.
211
        uint256 tokenCodeSize;
212
        assembly {
213
            tokenCodeSize := extcodesize(token)
214
        }
215
        require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
216

                            
                        
217
        bool success;
218
        bytes memory returnData;
219

                            
                        
220
        // 4-byte selector for `isBlacklisted(address)`, used by USDC.
221
        (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr));
222
        vm.assume(!success || abi.decode(returnData, (bool)) == false);
223

                            
                        
224
        // 4-byte selector for `isBlackListed(address)`, used by USDT.
225
        (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr));
226
        vm.assume(!success || abi.decode(returnData, (bool)) == false);
227
    }
228

                            
                        
229
    // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
230
    // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for
231
    // backwards compatibility, since this name was used in the original PR which has already has
232
    // a release. This function can be removed in a future release once we want a breaking change.
233
    function assumeNoBlacklisted(address token, address addr) internal view virtual {
234
        assumeNotBlacklisted(token, addr);
235
    }
236

                            
                        
237
    function assumeAddressIsNot(address addr, AddressType addressType) internal virtual {
238
        if (addressType == AddressType.Payable) {
239
            assumeNotPayable(addr);
240
        } else if (addressType == AddressType.NonPayable) {
241
            assumePayable(addr);
242
        } else if (addressType == AddressType.ZeroAddress) {
243
            assumeNotZeroAddress(addr);
244
        } else if (addressType == AddressType.Precompile) {
245
            assumeNotPrecompile(addr);
246
        } else if (addressType == AddressType.ForgeAddress) {
247
            assumeNotForgeAddress(addr);
248
        }
249
    }
250

                            
                        
251
    function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual {
252
        assumeAddressIsNot(addr, addressType1);
253
        assumeAddressIsNot(addr, addressType2);
254
    }
255

                            
                        
256
    function assumeAddressIsNot(
257
        address addr,
258
        AddressType addressType1,
259
        AddressType addressType2,
260
        AddressType addressType3
261
    ) internal virtual {
262
        assumeAddressIsNot(addr, addressType1);
263
        assumeAddressIsNot(addr, addressType2);
264
        assumeAddressIsNot(addr, addressType3);
265
    }
266

                            
                        
267
    function assumeAddressIsNot(
268
        address addr,
269
        AddressType addressType1,
270
        AddressType addressType2,
271
        AddressType addressType3,
272
        AddressType addressType4
273
    ) internal virtual {
274
        assumeAddressIsNot(addr, addressType1);
275
        assumeAddressIsNot(addr, addressType2);
276
        assumeAddressIsNot(addr, addressType3);
277
        assumeAddressIsNot(addr, addressType4);
278
    }
279

                            
                        
280
    // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to
281
    // `addr` and checking the `success` return value.
282
    // NOTE: This function may result in state changes depending on the fallback/receive logic
283
    // implemented by `addr`, which should be taken into account when this function is used.
284
    function _isPayable(address addr) private returns (bool) {
285
        require(
286
            addr.balance < UINT256_MAX,
287
            "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds"
288
        );
289
        uint256 origBalanceTest = address(this).balance;
290
        uint256 origBalanceAddr = address(addr).balance;
291

                            
                        
292
        vm.deal(address(this), 1);
293
        (bool success,) = payable(addr).call{value: 1}("");
294

                            
                        
295
        // reset balances
296
        vm.deal(address(this), origBalanceTest);
297
        vm.deal(addr, origBalanceAddr);
298

                            
                        
299
        return success;
300
    }
301

                            
                        
302
    // NOTE: This function may result in state changes depending on the fallback/receive logic
303
    // implemented by `addr`, which should be taken into account when this function is used. See the
304
    // `_isPayable` method for more information.
305
    function assumePayable(address addr) internal virtual {
306
        vm.assume(_isPayable(addr));
307
    }
308

                            
                        
309
    function assumeNotPayable(address addr) internal virtual {
310
        vm.assume(!_isPayable(addr));
311
    }
312

                            
                        
313
    function assumeNotZeroAddress(address addr) internal pure virtual {
314
        vm.assume(addr != address(0));
315
    }
316

                            
                        
317
    function assumeNotPrecompile(address addr) internal pure virtual {
318
        assumeNotPrecompile(addr, _pureChainId());
319
    }
320

                            
                        
321
    function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual {
322
        // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific
323
        // address), but the same rationale for excluding them applies so we include those too.
324

                            
                        
325
        // These are reserved by Ethereum and may be on all EVM-compatible chains.
326
        vm.assume(addr < address(0x1) || addr > address(0xff));
327

                            
                        
328
        // forgefmt: disable-start
329
        if (chainId == 10 || chainId == 420) {
330
            // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
331
            vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));
332
        } else if (chainId == 42161 || chainId == 421613) {
333
            // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
334
            vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));
335
        } else if (chainId == 43114 || chainId == 43113) {
336
            // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
337
            vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));
338
            vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));
339
            vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));
340
        }
341
        // forgefmt: disable-end
342
    }
343

                            
                        
344
    function assumeNotForgeAddress(address addr) internal pure virtual {
345
        // vm, console, and Create2Deployer addresses
346
        vm.assume(
347
            addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
348
                && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
349
        );
350
    }
351

                            
                        
352
    function readEIP1559ScriptArtifact(string memory path)
353
        internal
354
        view
355
        virtual
356
        returns (EIP1559ScriptArtifact memory)
357
    {
358
        string memory data = vm.readFile(path);
359
        bytes memory parsedData = vm.parseJson(data);
360
        RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
361
        EIP1559ScriptArtifact memory artifact;
362
        artifact.libraries = rawArtifact.libraries;
363
        artifact.path = rawArtifact.path;
364
        artifact.timestamp = rawArtifact.timestamp;
365
        artifact.pending = rawArtifact.pending;
366
        artifact.txReturns = rawArtifact.txReturns;
367
        artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
368
        artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
369
        return artifact;
370
    }
371

                            
                        
372
    function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
373
        Tx1559[] memory txs = new Tx1559[](rawTxs.length);
374
        for (uint256 i; i < rawTxs.length; i++) {
375
            txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
376
        }
377
        return txs;
378
    }
379

                            
                        
380
    function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
381
        Tx1559 memory transaction;
382
        transaction.arguments = rawTx.arguments;
383
        transaction.contractName = rawTx.contractName;
384
        transaction.functionSig = rawTx.functionSig;
385
        transaction.hash = rawTx.hash;
386
        transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
387
        transaction.opcode = rawTx.opcode;
388
        return transaction;
389
    }
390

                            
                        
391
    function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
392
        internal
393
        pure
394
        virtual
395
        returns (Tx1559Detail memory)
396
    {
397
        Tx1559Detail memory txDetail;
398
        txDetail.data = rawDetail.data;
399
        txDetail.from = rawDetail.from;
400
        txDetail.to = rawDetail.to;
401
        txDetail.nonce = _bytesToUint(rawDetail.nonce);
402
        txDetail.txType = _bytesToUint(rawDetail.txType);
403
        txDetail.value = _bytesToUint(rawDetail.value);
404
        txDetail.gas = _bytesToUint(rawDetail.gas);
405
        txDetail.accessList = rawDetail.accessList;
406
        return txDetail;
407
    }
408

                            
                        
409
    function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
410
        string memory deployData = vm.readFile(path);
411
        bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions");
412
        RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
413
        return rawToConvertedEIPTx1559s(rawTxs);
414
    }
415

                            
                        
416
    function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
417
        string memory deployData = vm.readFile(path);
418
        string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
419
        bytes memory parsedDeployData = vm.parseJson(deployData, key);
420
        RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
421
        return rawToConvertedEIPTx1559(rawTx);
422
    }
423

                            
                        
424
    // Analogous to readTransactions, but for receipts.
425
    function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
426
        string memory deployData = vm.readFile(path);
427
        bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
428
        RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
429
        return rawToConvertedReceipts(rawReceipts);
430
    }
431

                            
                        
432
    function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
433
        string memory deployData = vm.readFile(path);
434
        string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
435
        bytes memory parsedDeployData = vm.parseJson(deployData, key);
436
        RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
437
        return rawToConvertedReceipt(rawReceipt);
438
    }
439

                            
                        
440
    function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
441
        Receipt[] memory receipts = new Receipt[](rawReceipts.length);
442
        for (uint256 i; i < rawReceipts.length; i++) {
443
            receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
444
        }
445
        return receipts;
446
    }
447

                            
                        
448
    function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
449
        Receipt memory receipt;
450
        receipt.blockHash = rawReceipt.blockHash;
451
        receipt.to = rawReceipt.to;
452
        receipt.from = rawReceipt.from;
453
        receipt.contractAddress = rawReceipt.contractAddress;
454
        receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
455
        receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
456
        receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
457
        receipt.status = _bytesToUint(rawReceipt.status);
458
        receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
459
        receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
460
        receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
461
        receipt.logsBloom = rawReceipt.logsBloom;
462
        receipt.transactionHash = rawReceipt.transactionHash;
463
        return receipt;
464
    }
465

                            
                        
466
    function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
467
        internal
468
        pure
469
        virtual
470
        returns (ReceiptLog[] memory)
471
    {
472
        ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
473
        for (uint256 i; i < rawLogs.length; i++) {
474
            logs[i].logAddress = rawLogs[i].logAddress;
475
            logs[i].blockHash = rawLogs[i].blockHash;
476
            logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
477
            logs[i].data = rawLogs[i].data;
478
            logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
479
            logs[i].topics = rawLogs[i].topics;
480
            logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
481
            logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
482
            logs[i].removed = rawLogs[i].removed;
483
        }
484
        return logs;
485
    }
486

                            
                        
487
    // Deploy a contract by fetching the contract bytecode from
488
    // the artifacts directory
489
    // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
490
    function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
491
        bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
492
        /// @solidity memory-safe-assembly
493
        assembly {
494
            addr := create(0, add(bytecode, 0x20), mload(bytecode))
495
        }
496

                            
                        
497
        require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
498
    }
499

                            
                        
500
    function deployCode(string memory what) internal virtual returns (address addr) {
501
        bytes memory bytecode = vm.getCode(what);
502
        /// @solidity memory-safe-assembly
503
        assembly {
504
            addr := create(0, add(bytecode, 0x20), mload(bytecode))
505
        }
506

                            
                        
507
        require(addr != address(0), "StdCheats deployCode(string): Deployment failed.");
508
    }
509

                            
                        
510
    /// @dev deploy contract with value on construction
511
    function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
512
        bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
513
        /// @solidity memory-safe-assembly
514
        assembly {
515
            addr := create(val, add(bytecode, 0x20), mload(bytecode))
516
        }
517

                            
                        
518
        require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
519
    }
520

                            
                        
521
    function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
522
        bytes memory bytecode = vm.getCode(what);
523
        /// @solidity memory-safe-assembly
524
        assembly {
525
            addr := create(val, add(bytecode, 0x20), mload(bytecode))
526
        }
527

                            
                        
528
        require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
529
    }
530

                            
                        
531
    // creates a labeled address and the corresponding private key
532
    function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
533
        privateKey = uint256(keccak256(abi.encodePacked(name)));
534
        addr = vm.addr(privateKey);
535
        vm.label(addr, name);
536
    }
537

                            
                        
538
    // creates a labeled address
539
    function makeAddr(string memory name) internal virtual returns (address addr) {
540
        (addr,) = makeAddrAndKey(name);
541
    }
542

                            
                        
543
    // Destroys an account immediately, sending the balance to beneficiary.
544
    // Destroying means: balance will be zero, code will be empty, and nonce will be 0
545
    // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce
546
    // only after tx ends, this will run immediately.
547
    function destroyAccount(address who, address beneficiary) internal virtual {
548
        uint256 currBalance = who.balance;
549
        vm.etch(who, abi.encode());
550
        vm.deal(who, 0);
551
        vm.resetNonce(who);
552

                            
                        
553
        uint256 beneficiaryBalance = beneficiary.balance;
554
        vm.deal(beneficiary, currBalance + beneficiaryBalance);
555
    }
556

                            
                        
557
    // creates a struct containing both a labeled address and the corresponding private key
558
    function makeAccount(string memory name) internal virtual returns (Account memory account) {
559
        (account.addr, account.key) = makeAddrAndKey(name);
560
    }
561

                            
                        
562
    function deriveRememberKey(string memory mnemonic, uint32 index)
563
        internal
564
        virtual
565
        returns (address who, uint256 privateKey)
566
    {
567
        privateKey = vm.deriveKey(mnemonic, index);
568
        who = vm.rememberKey(privateKey);
569
    }
570

                            
                        
571
    function _bytesToUint(bytes memory b) private pure returns (uint256) {
572
        require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
573
        return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
574
    }
575

                            
                        
576
    function isFork() internal view virtual returns (bool status) {
577
        try vm.activeFork() {
578
            status = true;
579
        } catch (bytes memory) {}
580
    }
581

                            
                        
582
    modifier skipWhenForking() {
583
        if (!isFork()) {
584
            _;
585
        }
586
    }
587

                            
                        
588
    modifier skipWhenNotForking() {
589
        if (isFork()) {
590
            _;
591
        }
592
    }
593

                            
                        
594
    modifier noGasMetering() {
595
        vm.pauseGasMetering();
596
        // To prevent turning gas monitoring back on with nested functions that use this modifier,
597
        // we check if gasMetering started in the off position. If it did, we don't want to turn
598
        // it back on until we exit the top level function that used the modifier
599
        //
600
        // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
601
        // funcA will have `gasStartedOff` as false, funcB will have it as true,
602
        // so we only turn metering back on at the end of the funcA
603
        bool gasStartedOff = gasMeteringOff;
604
        gasMeteringOff = true;
605

                            
                        
606
        _;
607

                            
                        
608
        // if gas metering was on when this modifier was called, turn it back on at the end
609
        if (!gasStartedOff) {
610
            gasMeteringOff = false;
611
            vm.resumeGasMetering();
612
        }
613
    }
614

                            
                        
615
    // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
616
    // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
617
    // can't simply access the chain ID in a normal view or pure function because the solc View Pure
618
    // Checker changed `chainid` from pure to view in 0.8.0.
619
    function _viewChainId() private view returns (uint256 chainId) {
620
        // Assembly required since `block.chainid` was introduced in 0.8.0.
621
        assembly {
622
            chainId := chainid()
623
        }
624

                            
                        
625
        address(this); // Silence warnings in older Solc versions.
626
    }
627

                            
                        
628
    function _pureChainId() private pure returns (uint256 chainId) {
629
        function() internal view returns (uint256) fnIn = _viewChainId;
630
        function() internal pure returns (uint256) pureChainId;
631
        assembly {
632
            pureChainId := fnIn
633
        }
634
        chainId = pureChainId();
635
    }
636
}
637

                            
                        
638
// Wrappers around cheatcodes to avoid footguns
639
abstract contract StdCheats is StdCheatsSafe {
640
    using stdStorage for StdStorage;
641

                            
                        
642
    StdStorage private stdstore;
643
    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
644
    address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
645

                            
                        
646
    // Skip forward or rewind time by the specified number of seconds
647
    function skip(uint256 time) internal virtual {
648
        vm.warp(block.timestamp + time);
649
    }
650

                            
                        
651
    function rewind(uint256 time) internal virtual {
652
        vm.warp(block.timestamp - time);
653
    }
654

                            
                        
655
    // Setup a prank from an address that has some ether
656
    function hoax(address msgSender) internal virtual {
657
        vm.deal(msgSender, 1 << 128);
658
        vm.prank(msgSender);
659
    }
660

                            
                        
661
    function hoax(address msgSender, uint256 give) internal virtual {
662
        vm.deal(msgSender, give);
663
        vm.prank(msgSender);
664
    }
665

                            
                        
666
    function hoax(address msgSender, address origin) internal virtual {
667
        vm.deal(msgSender, 1 << 128);
668
        vm.prank(msgSender, origin);
669
    }
670

                            
                        
671
    function hoax(address msgSender, address origin, uint256 give) internal virtual {
672
        vm.deal(msgSender, give);
673
        vm.prank(msgSender, origin);
674
    }
675

                            
                        
676
    // Start perpetual prank from an address that has some ether
677
    function startHoax(address msgSender) internal virtual {
678
        vm.deal(msgSender, 1 << 128);
679
        vm.startPrank(msgSender);
680
    }
681

                            
                        
682
    function startHoax(address msgSender, uint256 give) internal virtual {
683
        vm.deal(msgSender, give);
684
        vm.startPrank(msgSender);
685
    }
686

                            
                        
687
    // Start perpetual prank from an address that has some ether
688
    // tx.origin is set to the origin parameter
689
    function startHoax(address msgSender, address origin) internal virtual {
690
        vm.deal(msgSender, 1 << 128);
691
        vm.startPrank(msgSender, origin);
692
    }
693

                            
                        
694
    function startHoax(address msgSender, address origin, uint256 give) internal virtual {
695
        vm.deal(msgSender, give);
696
        vm.startPrank(msgSender, origin);
697
    }
698

                            
                        
699
    function changePrank(address msgSender) internal virtual {
700
        console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
701
        vm.stopPrank();
702
        vm.startPrank(msgSender);
703
    }
704

                            
                        
705
    function changePrank(address msgSender, address txOrigin) internal virtual {
706
        vm.stopPrank();
707
        vm.startPrank(msgSender, txOrigin);
708
    }
709

                            
                        
710
    // The same as Vm's `deal`
711
    // Use the alternative signature for ERC20 tokens
712
    function deal(address to, uint256 give) internal virtual {
713
        vm.deal(to, give);
714
    }
715

                            
                        
716
    // Set the balance of an account for any ERC20 token
717
    // Use the alternative signature to update `totalSupply`
718
    function deal(address token, address to, uint256 give) internal virtual {
719
        deal(token, to, give, false);
720
    }
721

                            
                        
722
    // Set the balance of an account for any ERC1155 token
723
    // Use the alternative signature to update `totalSupply`
724
    function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {
725
        dealERC1155(token, to, id, give, false);
726
    }
727

                            
                        
728
    function deal(address token, address to, uint256 give, bool adjust) internal virtual {
729
        // get current balance
730
        (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
731
        uint256 prevBal = abi.decode(balData, (uint256));
732

                            
                        
733
        // update balance
734
        stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
735

                            
                        
736
        // update total supply
737
        if (adjust) {
738
            (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd));
739
            uint256 totSup = abi.decode(totSupData, (uint256));
740
            if (give < prevBal) {
741
                totSup -= (prevBal - give);
742
            } else {
743
                totSup += (give - prevBal);
744
            }
745
            stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
746
        }
747
    }
748

                            
                        
749
    function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {
750
        // get current balance
751
        (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id));
752
        uint256 prevBal = abi.decode(balData, (uint256));
753

                            
                        
754
        // update balance
755
        stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);
756

                            
                        
757
        // update total supply
758
        if (adjust) {
759
            (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id));
760
            require(
761
                totSupData.length != 0,
762
                "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply."
763
            );
764
            uint256 totSup = abi.decode(totSupData, (uint256));
765
            if (give < prevBal) {
766
                totSup -= (prevBal - give);
767
            } else {
768
                totSup += (give - prevBal);
769
            }
770
            stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);
771
        }
772
    }
773

                            
                        
774
    function dealERC721(address token, address to, uint256 id) internal virtual {
775
        // check if token id is already minted and the actual owner.
776
        (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));
777
        require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted.");
778

                            
                        
779
        // get owner current balance
780
        (, bytes memory fromBalData) =
781
            token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));
782
        uint256 fromPrevBal = abi.decode(fromBalData, (uint256));
783

                            
                        
784
        // get new user current balance
785
        (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
786
        uint256 toPrevBal = abi.decode(toBalData, (uint256));
787

                            
                        
788
        // update balances
789
        stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);
790
        stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);
791

                            
                        
792
        // update owner
793
        stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);
794
    }
795

                            
                        
796
    function deployCodeTo(string memory what, address where) internal virtual {
797
        deployCodeTo(what, "", 0, where);
798
    }
799

                            
                        
800
    function deployCodeTo(string memory what, bytes memory args, address where) internal virtual {
801
        deployCodeTo(what, args, 0, where);
802
    }
803

                            
                        
804
    function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual {
805
        bytes memory creationCode = vm.getCode(what);
806
        vm.etch(where, abi.encodePacked(creationCode, args));
807
        (bool success, bytes memory runtimeBytecode) = where.call{value: value}("");
808
        require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
809
        vm.etch(where, runtimeBytecode);
810
    }
811

                            
                        
812
    // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.
813
    function console2_log_StdCheats(string memory p0) private view {
814
        (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
815
        status;
816
    }
817
}
818

                            
                        

Lines covered: 0 / 10 (0.0%)

1
// SPDX-License-Identifier: MIT
2
// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test
3
pragma solidity >=0.6.2 <0.9.0;
4

                            
                        
5
library stdError {
6
    bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01);
7
    bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11);
8
    bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12);
9
    bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21);
10
    bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22);
11
    bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31);
12
    bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32);
13
    bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41);
14
    bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51);
15
}
16

                            
                        

Lines covered: 0 / 20 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
pragma experimental ABIEncoderV2;
5

                            
                        
6
abstract contract StdInvariant {
7
    struct FuzzSelector {
8
        address addr;
9
        bytes4[] selectors;
10
    }
11

                            
                        
12
    struct FuzzArtifactSelector {
13
        string artifact;
14
        bytes4[] selectors;
15
    }
16

                            
                        
17
    struct FuzzInterface {
18
        address addr;
19
        string[] artifacts;
20
    }
21

                            
                        
22
    address[] private _excludedContracts;
23
    address[] private _excludedSenders;
24
    address[] private _targetedContracts;
25
    address[] private _targetedSenders;
26

                            
                        
27
    string[] private _excludedArtifacts;
28
    string[] private _targetedArtifacts;
29

                            
                        
30
    FuzzArtifactSelector[] private _targetedArtifactSelectors;
31

                            
                        
32
    FuzzSelector[] private _excludedSelectors;
33
    FuzzSelector[] private _targetedSelectors;
34

                            
                        
35
    FuzzInterface[] private _targetedInterfaces;
36

                            
                        
37
    // Functions for users:
38
    // These are intended to be called in tests.
39

                            
                        
40
    function excludeContract(address newExcludedContract_) internal {
41
        _excludedContracts.push(newExcludedContract_);
42
    }
43

                            
                        
44
    function excludeSelector(FuzzSelector memory newExcludedSelector_) internal {
45
        _excludedSelectors.push(newExcludedSelector_);
46
    }
47

                            
                        
48
    function excludeSender(address newExcludedSender_) internal {
49
        _excludedSenders.push(newExcludedSender_);
50
    }
51

                            
                        
52
    function excludeArtifact(string memory newExcludedArtifact_) internal {
53
        _excludedArtifacts.push(newExcludedArtifact_);
54
    }
55

                            
                        
56
    function targetArtifact(string memory newTargetedArtifact_) internal {
57
        _targetedArtifacts.push(newTargetedArtifact_);
58
    }
59

                            
                        
60
    function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal {
61
        _targetedArtifactSelectors.push(newTargetedArtifactSelector_);
62
    }
63

                            
                        
64
    function targetContract(address newTargetedContract_) internal {
65
        _targetedContracts.push(newTargetedContract_);
66
    }
67

                            
                        
68
    function targetSelector(FuzzSelector memory newTargetedSelector_) internal {
69
        _targetedSelectors.push(newTargetedSelector_);
70
    }
71

                            
                        
72
    function targetSender(address newTargetedSender_) internal {
73
        _targetedSenders.push(newTargetedSender_);
74
    }
75

                            
                        
76
    function targetInterface(FuzzInterface memory newTargetedInterface_) internal {
77
        _targetedInterfaces.push(newTargetedInterface_);
78
    }
79

                            
                        
80
    // Functions for forge:
81
    // These are called by forge to run invariant tests and don't need to be called in tests.
82

                            
                        
83
    function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {
84
        excludedArtifacts_ = _excludedArtifacts;
85
    }
86

                            
                        
87
    function excludeContracts() public view returns (address[] memory excludedContracts_) {
88
        excludedContracts_ = _excludedContracts;
89
    }
90

                            
                        
91
    function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) {
92
        excludedSelectors_ = _excludedSelectors;
93
    }
94

                            
                        
95
    function excludeSenders() public view returns (address[] memory excludedSenders_) {
96
        excludedSenders_ = _excludedSenders;
97
    }
98

                            
                        
99
    function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {
100
        targetedArtifacts_ = _targetedArtifacts;
101
    }
102

                            
                        
103
    function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) {
104
        targetedArtifactSelectors_ = _targetedArtifactSelectors;
105
    }
106

                            
                        
107
    function targetContracts() public view returns (address[] memory targetedContracts_) {
108
        targetedContracts_ = _targetedContracts;
109
    }
110

                            
                        
111
    function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {
112
        targetedSelectors_ = _targetedSelectors;
113
    }
114

                            
                        
115
    function targetSenders() public view returns (address[] memory targetedSenders_) {
116
        targetedSenders_ = _targetedSenders;
117
    }
118

                            
                        
119
    function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) {
120
        targetedInterfaces_ = _targetedInterfaces;
121
    }
122
}
123

                            
                        

Lines covered: 0 / 1 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.0 <0.9.0;
3

                            
                        
4
pragma experimental ABIEncoderV2;
5

                            
                        
6
import {VmSafe} from "./Vm.sol";
7

                            
                        
8
// Helpers for parsing and writing JSON files
9
// To parse:
10
// ```
11
// using stdJson for string;
12
// string memory json = vm.readFile("<some_path>");
13
// json.readUint("<json_path>");
14
// ```
15
// To write:
16
// ```
17
// using stdJson for string;
18
// string memory json = "json";
19
// json.serialize("a", uint256(123));
20
// string memory semiFinal = json.serialize("b", string("test"));
21
// string memory finalJson = json.serialize("c", semiFinal);
22
// finalJson.write("<some_path>");
23
// ```
24

                            
                        
25
library stdJson {
26
    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
27

                            
                        
28
    function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {
29
        return vm.parseJson(json, key);
30
    }
31

                            
                        
32
    function readUint(string memory json, string memory key) internal pure returns (uint256) {
33
        return vm.parseJsonUint(json, key);
34
    }
35

                            
                        
36
    function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {
37
        return vm.parseJsonUintArray(json, key);
38
    }
39

                            
                        
40
    function readInt(string memory json, string memory key) internal pure returns (int256) {
41
        return vm.parseJsonInt(json, key);
42
    }
43

                            
                        
44
    function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {
45
        return vm.parseJsonIntArray(json, key);
46
    }
47

                            
                        
48
    function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {
49
        return vm.parseJsonBytes32(json, key);
50
    }
51

                            
                        
52
    function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {
53
        return vm.parseJsonBytes32Array(json, key);
54
    }
55

                            
                        
56
    function readString(string memory json, string memory key) internal pure returns (string memory) {
57
        return vm.parseJsonString(json, key);
58
    }
59

                            
                        
60
    function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {
61
        return vm.parseJsonStringArray(json, key);
62
    }
63

                            
                        
64
    function readAddress(string memory json, string memory key) internal pure returns (address) {
65
        return vm.parseJsonAddress(json, key);
66
    }
67

                            
                        
68
    function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {
69
        return vm.parseJsonAddressArray(json, key);
70
    }
71

                            
                        
72
    function readBool(string memory json, string memory key) internal pure returns (bool) {
73
        return vm.parseJsonBool(json, key);
74
    }
75

                            
                        
76
    function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {
77
        return vm.parseJsonBoolArray(json, key);
78
    }
79

                            
                        
80
    function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {
81
        return vm.parseJsonBytes(json, key);
82
    }
83

                            
                        
84
    function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {
85
        return vm.parseJsonBytesArray(json, key);
86
    }
87

                            
                        
88
    function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
89
        return vm.serializeJson(jsonKey, rootObject);
90
    }
91

                            
                        
92
    function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
93
        return vm.serializeBool(jsonKey, key, value);
94
    }
95

                            
                        
96
    function serialize(string memory jsonKey, string memory key, bool[] memory value)
97
        internal
98
        returns (string memory)
99
    {
100
        return vm.serializeBool(jsonKey, key, value);
101
    }
102

                            
                        
103
    function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
104
        return vm.serializeUint(jsonKey, key, value);
105
    }
106

                            
                        
107
    function serialize(string memory jsonKey, string memory key, uint256[] memory value)
108
        internal
109
        returns (string memory)
110
    {
111
        return vm.serializeUint(jsonKey, key, value);
112
    }
113

                            
                        
114
    function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
115
        return vm.serializeInt(jsonKey, key, value);
116
    }
117

                            
                        
118
    function serialize(string memory jsonKey, string memory key, int256[] memory value)
119
        internal
120
        returns (string memory)
121
    {
122
        return vm.serializeInt(jsonKey, key, value);
123
    }
124

                            
                        
125
    function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
126
        return vm.serializeAddress(jsonKey, key, value);
127
    }
128

                            
                        
129
    function serialize(string memory jsonKey, string memory key, address[] memory value)
130
        internal
131
        returns (string memory)
132
    {
133
        return vm.serializeAddress(jsonKey, key, value);
134
    }
135

                            
                        
136
    function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
137
        return vm.serializeBytes32(jsonKey, key, value);
138
    }
139

                            
                        
140
    function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
141
        internal
142
        returns (string memory)
143
    {
144
        return vm.serializeBytes32(jsonKey, key, value);
145
    }
146

                            
                        
147
    function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
148
        return vm.serializeBytes(jsonKey, key, value);
149
    }
150

                            
                        
151
    function serialize(string memory jsonKey, string memory key, bytes[] memory value)
152
        internal
153
        returns (string memory)
154
    {
155
        return vm.serializeBytes(jsonKey, key, value);
156
    }
157

                            
                        
158
    function serialize(string memory jsonKey, string memory key, string memory value)
159
        internal
160
        returns (string memory)
161
    {
162
        return vm.serializeString(jsonKey, key, value);
163
    }
164

                            
                        
165
    function serialize(string memory jsonKey, string memory key, string[] memory value)
166
        internal
167
        returns (string memory)
168
    {
169
        return vm.serializeString(jsonKey, key, value);
170
    }
171

                            
                        
172
    function write(string memory jsonKey, string memory path) internal {
173
        vm.writeJson(jsonKey, path);
174
    }
175

                            
                        
176
    function write(string memory jsonKey, string memory path, string memory valueKey) internal {
177
        vm.writeJson(jsonKey, path, valueKey);
178
    }
179
}
180

                            
                        

Lines covered: 0 / 1 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
library stdMath {
5
    int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;
6

                            
                        
7
    function abs(int256 a) internal pure returns (uint256) {
8
        // Required or it will fail when `a = type(int256).min`
9
        if (a == INT256_MIN) {
10
            return 57896044618658097711785492504343953926634992332820282019728792003956564819968;
11
        }
12

                            
                        
13
        return uint256(a > 0 ? a : -a);
14
    }
15

                            
                        
16
    function delta(uint256 a, uint256 b) internal pure returns (uint256) {
17
        return a > b ? a - b : b - a;
18
    }
19

                            
                        
20
    function delta(int256 a, int256 b) internal pure returns (uint256) {
21
        // a and b are of the same sign
22
        // this works thanks to two's complement, the left-most bit is the sign bit
23
        if ((a ^ b) > -1) {
24
            return delta(abs(a), abs(b));
25
        }
26

                            
                        
27
        // a and b are of opposite signs
28
        return abs(a) + abs(b);
29
    }
30

                            
                        
31
    function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
32
        uint256 absDelta = delta(a, b);
33

                            
                        
34
        return absDelta * 1e18 / b;
35
    }
36

                            
                        
37
    function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
38
        uint256 absDelta = delta(a, b);
39
        uint256 absB = abs(b);
40

                            
                        
41
        return absDelta * 1e18 / absB;
42
    }
43
}
44

                            
                        

Lines covered: 0 / 2 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
import {Vm} from "./Vm.sol";
5

                            
                        
6
struct FindData {
7
    uint256 slot;
8
    uint256 offsetLeft;
9
    uint256 offsetRight;
10
    bool found;
11
}
12

                            
                        
13
struct StdStorage {
14
    mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds;
15
    bytes32[] _keys;
16
    bytes4 _sig;
17
    uint256 _depth;
18
    address _target;
19
    bytes32 _set;
20
    bool _enable_packed_slots;
21
    bytes _calldata;
22
}
23

                            
                        
24
library stdStorageSafe {
25
    event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);
26
    event WARNING_UninitedSlot(address who, uint256 slot);
27

                            
                        
28
    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
29
    uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
30

                            
                        
31
    function sigs(string memory sigStr) internal pure returns (bytes4) {
32
        return bytes4(keccak256(bytes(sigStr)));
33
    }
34

                            
                        
35
    function getCallParams(StdStorage storage self) internal view returns (bytes memory) {
36
        if (self._calldata.length == 0) {
37
            return flatten(self._keys);
38
        } else {
39
            return self._calldata;
40
        }
41
    }
42

                            
                        
43
    // Calls target contract with configured parameters
44
    function callTarget(StdStorage storage self) internal view returns (bool, bytes32) {
45
        bytes memory cald = abi.encodePacked(self._sig, getCallParams(self));
46
        (bool success, bytes memory rdat) = self._target.staticcall(cald);
47
        bytes32 result = bytesToBytes32(rdat, 32 * self._depth);
48

                            
                        
49
        return (success, result);
50
    }
51

                            
                        
52
    // Tries mutating slot value to determine if the targeted value is stored in it.
53
    // If current value is 0, then we are setting slot value to type(uint256).max
54
    // Otherwise, we set it to 0. That way, return value should always be affected.
55
    function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) {
56
        bytes32 prevSlotValue = vm.load(self._target, slot);
57
        (bool success, bytes32 prevReturnValue) = callTarget(self);
58

                            
                        
59
        bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0);
60
        vm.store(self._target, slot, testVal);
61

                            
                        
62
        (, bytes32 newReturnValue) = callTarget(self);
63

                            
                        
64
        vm.store(self._target, slot, prevSlotValue);
65

                            
                        
66
        return (success && (prevReturnValue != newReturnValue));
67
    }
68

                            
                        
69
    // Tries setting one of the bits in slot to 1 until return value changes.
70
    // Index of resulted bit is an offset packed slot has from left/right side
71
    function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) {
72
        for (uint256 offset = 0; offset < 256; offset++) {
73
            uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset);
74
            vm.store(self._target, slot, bytes32(valueToPut));
75

                            
                        
76
            (bool success, bytes32 data) = callTarget(self);
77

                            
                        
78
            if (success && (uint256(data) > 0)) {
79
                return (true, offset);
80
            }
81
        }
82
        return (false, 0);
83
    }
84

                            
                        
85
    function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) {
86
        bytes32 prevSlotValue = vm.load(self._target, slot);
87

                            
                        
88
        (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true);
89
        (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false);
90

                            
                        
91
        // `findOffset` may mutate slot value, so we are setting it to initial value
92
        vm.store(self._target, slot, prevSlotValue);
93
        return (foundLeft && foundRight, offsetLeft, offsetRight);
94
    }
95

                            
                        
96
    function find(StdStorage storage self) internal returns (FindData storage) {
97
        return find(self, true);
98
    }
99

                            
                        
100
    /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against
101
    // slot complexity:
102
    //  if flat, will be bytes32(uint256(uint));
103
    //  if map, will be keccak256(abi.encode(key, uint(slot)));
104
    //  if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));
105
    //  if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);
106
    function find(StdStorage storage self, bool _clear) internal returns (FindData storage) {
107
        address who = self._target;
108
        bytes4 fsig = self._sig;
109
        uint256 field_depth = self._depth;
110
        bytes memory params = getCallParams(self);
111

                            
                        
112
        // calldata to test against
113
        if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
114
            if (_clear) {
115
                clear(self);
116
            }
117
            return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
118
        }
119
        vm.record();
120
        (, bytes32 callResult) = callTarget(self);
121
        (bytes32[] memory reads,) = vm.accesses(address(who));
122

                            
                        
123
        if (reads.length == 0) {
124
            revert("stdStorage find(StdStorage): No storage use detected for target.");
125
        } else {
126
            for (uint256 i = reads.length; --i >= 0;) {
127
                bytes32 prev = vm.load(who, reads[i]);
128
                if (prev == bytes32(0)) {
129
                    emit WARNING_UninitedSlot(who, uint256(reads[i]));
130
                }
131

                            
                        
132
                if (!checkSlotMutatesCall(self, reads[i])) {
133
                    continue;
134
                }
135

                            
                        
136
                (uint256 offsetLeft, uint256 offsetRight) = (0, 0);
137

                            
                        
138
                if (self._enable_packed_slots) {
139
                    bool found;
140
                    (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]);
141
                    if (!found) {
142
                        continue;
143
                    }
144
                }
145

                            
                        
146
                // Check that value between found offsets is equal to the current call result
147
                uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight;
148

                            
                        
149
                if (uint256(callResult) != curVal) {
150
                    continue;
151
                }
152

                            
                        
153
                emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i]));
154
                self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] =
155
                    FindData(uint256(reads[i]), offsetLeft, offsetRight, true);
156
                break;
157
            }
158
        }
159

                            
                        
160
        require(
161
            self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found,
162
            "stdStorage find(StdStorage): Slot(s) not found."
163
        );
164

                            
                        
165
        if (_clear) {
166
            clear(self);
167
        }
168
        return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
169
    }
170

                            
                        
171
    function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
172
        self._target = _target;
173
        return self;
174
    }
175

                            
                        
176
    function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
177
        self._sig = _sig;
178
        return self;
179
    }
180

                            
                        
181
    function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
182
        self._sig = sigs(_sig);
183
        return self;
184
    }
185

                            
                        
186
    function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
187
        self._calldata = _calldata;
188
        return self;
189
    }
190

                            
                        
191
    function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
192
        self._keys.push(bytes32(uint256(uint160(who))));
193
        return self;
194
    }
195

                            
                        
196
    function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
197
        self._keys.push(bytes32(amt));
198
        return self;
199
    }
200

                            
                        
201
    function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
202
        self._keys.push(key);
203
        return self;
204
    }
205

                            
                        
206
    function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
207
        self._enable_packed_slots = true;
208
        return self;
209
    }
210

                            
                        
211
    function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
212
        self._depth = _depth;
213
        return self;
214
    }
215

                            
                        
216
    function read(StdStorage storage self) private returns (bytes memory) {
217
        FindData storage data = find(self, false);
218
        uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight);
219
        uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight;
220
        clear(self);
221
        return abi.encode(value);
222
    }
223

                            
                        
224
    function read_bytes32(StdStorage storage self) internal returns (bytes32) {
225
        return abi.decode(read(self), (bytes32));
226
    }
227

                            
                        
228
    function read_bool(StdStorage storage self) internal returns (bool) {
229
        int256 v = read_int(self);
230
        if (v == 0) return false;
231
        if (v == 1) return true;
232
        revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
233
    }
234

                            
                        
235
    function read_address(StdStorage storage self) internal returns (address) {
236
        return abi.decode(read(self), (address));
237
    }
238

                            
                        
239
    function read_uint(StdStorage storage self) internal returns (uint256) {
240
        return abi.decode(read(self), (uint256));
241
    }
242

                            
                        
243
    function read_int(StdStorage storage self) internal returns (int256) {
244
        return abi.decode(read(self), (int256));
245
    }
246

                            
                        
247
    function parent(StdStorage storage self) internal returns (uint256, bytes32) {
248
        address who = self._target;
249
        uint256 field_depth = self._depth;
250
        vm.startMappingRecording();
251
        uint256 child = find(self, true).slot - field_depth;
252
        (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
253
        if (!found) {
254
            revert(
255
                "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
256
            );
257
        }
258
        return (uint256(parent_slot), key);
259
    }
260

                            
                        
261
    function root(StdStorage storage self) internal returns (uint256) {
262
        address who = self._target;
263
        uint256 field_depth = self._depth;
264
        vm.startMappingRecording();
265
        uint256 child = find(self, true).slot - field_depth;
266
        bool found;
267
        bytes32 root_slot;
268
        bytes32 parent_slot;
269
        (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
270
        if (!found) {
271
            revert(
272
                "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
273
            );
274
        }
275
        while (found) {
276
            root_slot = parent_slot;
277
            (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot));
278
        }
279
        return uint256(root_slot);
280
    }
281

                            
                        
282
    function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {
283
        bytes32 out;
284

                            
                        
285
        uint256 max = b.length > 32 ? 32 : b.length;
286
        for (uint256 i = 0; i < max; i++) {
287
            out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
288
        }
289
        return out;
290
    }
291

                            
                        
292
    function flatten(bytes32[] memory b) private pure returns (bytes memory) {
293
        bytes memory result = new bytes(b.length * 32);
294
        for (uint256 i = 0; i < b.length; i++) {
295
            bytes32 k = b[i];
296
            /// @solidity memory-safe-assembly
297
            assembly {
298
                mstore(add(result, add(32, mul(32, i))), k)
299
            }
300
        }
301

                            
                        
302
        return result;
303
    }
304

                            
                        
305
    function clear(StdStorage storage self) internal {
306
        delete self._target;
307
        delete self._sig;
308
        delete self._keys;
309
        delete self._depth;
310
        delete self._enable_packed_slots;
311
        delete self._calldata;
312
    }
313

                            
                        
314
    // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight`
315
    // (slotValue & mask) >> offsetRight will be the value of the given packed variable
316
    function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) {
317
        // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight;
318
        // using assembly because (1 << 256) causes overflow
319
        assembly {
320
            mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1))
321
        }
322
    }
323

                            
                        
324
    // Returns slot value with updated packed variable.
325
    function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight)
326
        internal
327
        pure
328
        returns (bytes32 newValue)
329
    {
330
        return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight));
331
    }
332
}
333

                            
                        
334
library stdStorage {
335
    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
336

                            
                        
337
    function sigs(string memory sigStr) internal pure returns (bytes4) {
338
        return stdStorageSafe.sigs(sigStr);
339
    }
340

                            
                        
341
    function find(StdStorage storage self) internal returns (uint256) {
342
        return find(self, true);
343
    }
344

                            
                        
345
    function find(StdStorage storage self, bool _clear) internal returns (uint256) {
346
        return stdStorageSafe.find(self, _clear).slot;
347
    }
348

                            
                        
349
    function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
350
        return stdStorageSafe.target(self, _target);
351
    }
352

                            
                        
353
    function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
354
        return stdStorageSafe.sig(self, _sig);
355
    }
356

                            
                        
357
    function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
358
        return stdStorageSafe.sig(self, _sig);
359
    }
360

                            
                        
361
    function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
362
        return stdStorageSafe.with_key(self, who);
363
    }
364

                            
                        
365
    function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
366
        return stdStorageSafe.with_key(self, amt);
367
    }
368

                            
                        
369
    function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
370
        return stdStorageSafe.with_key(self, key);
371
    }
372

                            
                        
373
    function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
374
        return stdStorageSafe.with_calldata(self, _calldata);
375
    }
376

                            
                        
377
    function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
378
        return stdStorageSafe.enable_packed_slots(self);
379
    }
380

                            
                        
381
    function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
382
        return stdStorageSafe.depth(self, _depth);
383
    }
384

                            
                        
385
    function clear(StdStorage storage self) internal {
386
        stdStorageSafe.clear(self);
387
    }
388

                            
                        
389
    function checked_write(StdStorage storage self, address who) internal {
390
        checked_write(self, bytes32(uint256(uint160(who))));
391
    }
392

                            
                        
393
    function checked_write(StdStorage storage self, uint256 amt) internal {
394
        checked_write(self, bytes32(amt));
395
    }
396

                            
                        
397
    function checked_write_int(StdStorage storage self, int256 val) internal {
398
        checked_write(self, bytes32(uint256(val)));
399
    }
400

                            
                        
401
    function checked_write(StdStorage storage self, bool write) internal {
402
        bytes32 t;
403
        /// @solidity memory-safe-assembly
404
        assembly {
405
            t := write
406
        }
407
        checked_write(self, t);
408
    }
409

                            
                        
410
    function checked_write(StdStorage storage self, bytes32 set) internal {
411
        address who = self._target;
412
        bytes4 fsig = self._sig;
413
        uint256 field_depth = self._depth;
414
        bytes memory params = stdStorageSafe.getCallParams(self);
415

                            
                        
416
        if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
417
            find(self, false);
418
        }
419
        FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
420
        if ((data.offsetLeft + data.offsetRight) > 0) {
421
            uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight));
422
            require(
423
                uint256(set) < maxVal,
424
                string(
425
                    abi.encodePacked(
426
                        "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ",
427
                        vm.toString(maxVal)
428
                    )
429
                )
430
            );
431
        }
432
        bytes32 curVal = vm.load(who, bytes32(data.slot));
433
        bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight);
434

                            
                        
435
        vm.store(who, bytes32(data.slot), valToSet);
436

                            
                        
437
        (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self);
438

                            
                        
439
        if (!success || callResult != set) {
440
            vm.store(who, bytes32(data.slot), curVal);
441
            revert("stdStorage find(StdStorage): Failed to write value.");
442
        }
443
        clear(self);
444
    }
445

                            
                        
446
    function read_bytes32(StdStorage storage self) internal returns (bytes32) {
447
        return stdStorageSafe.read_bytes32(self);
448
    }
449

                            
                        
450
    function read_bool(StdStorage storage self) internal returns (bool) {
451
        return stdStorageSafe.read_bool(self);
452
    }
453

                            
                        
454
    function read_address(StdStorage storage self) internal returns (address) {
455
        return stdStorageSafe.read_address(self);
456
    }
457

                            
                        
458
    function read_uint(StdStorage storage self) internal returns (uint256) {
459
        return stdStorageSafe.read_uint(self);
460
    }
461

                            
                        
462
    function read_int(StdStorage storage self) internal returns (int256) {
463
        return stdStorageSafe.read_int(self);
464
    }
465

                            
                        
466
    function parent(StdStorage storage self) internal returns (uint256, bytes32) {
467
        return stdStorageSafe.parent(self);
468
    }
469

                            
                        
470
    function root(StdStorage storage self) internal returns (uint256) {
471
        return stdStorageSafe.root(self);
472
    }
473
}
474

                            
                        

Lines covered: 0 / 1 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.4.22 <0.9.0;
3

                            
                        
4
import {VmSafe} from "./Vm.sol";
5

                            
                        
6
library StdStyle {
7
    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
8

                            
                        
9
    string constant RED = "\u001b[91m";
10
    string constant GREEN = "\u001b[92m";
11
    string constant YELLOW = "\u001b[93m";
12
    string constant BLUE = "\u001b[94m";
13
    string constant MAGENTA = "\u001b[95m";
14
    string constant CYAN = "\u001b[96m";
15
    string constant BOLD = "\u001b[1m";
16
    string constant DIM = "\u001b[2m";
17
    string constant ITALIC = "\u001b[3m";
18
    string constant UNDERLINE = "\u001b[4m";
19
    string constant INVERSE = "\u001b[7m";
20
    string constant RESET = "\u001b[0m";
21

                            
                        
22
    function styleConcat(string memory style, string memory self) private pure returns (string memory) {
23
        return string(abi.encodePacked(style, self, RESET));
24
    }
25

                            
                        
26
    function red(string memory self) internal pure returns (string memory) {
27
        return styleConcat(RED, self);
28
    }
29

                            
                        
30
    function red(uint256 self) internal pure returns (string memory) {
31
        return red(vm.toString(self));
32
    }
33

                            
                        
34
    function red(int256 self) internal pure returns (string memory) {
35
        return red(vm.toString(self));
36
    }
37

                            
                        
38
    function red(address self) internal pure returns (string memory) {
39
        return red(vm.toString(self));
40
    }
41

                            
                        
42
    function red(bool self) internal pure returns (string memory) {
43
        return red(vm.toString(self));
44
    }
45

                            
                        
46
    function redBytes(bytes memory self) internal pure returns (string memory) {
47
        return red(vm.toString(self));
48
    }
49

                            
                        
50
    function redBytes32(bytes32 self) internal pure returns (string memory) {
51
        return red(vm.toString(self));
52
    }
53

                            
                        
54
    function green(string memory self) internal pure returns (string memory) {
55
        return styleConcat(GREEN, self);
56
    }
57

                            
                        
58
    function green(uint256 self) internal pure returns (string memory) {
59
        return green(vm.toString(self));
60
    }
61

                            
                        
62
    function green(int256 self) internal pure returns (string memory) {
63
        return green(vm.toString(self));
64
    }
65

                            
                        
66
    function green(address self) internal pure returns (string memory) {
67
        return green(vm.toString(self));
68
    }
69

                            
                        
70
    function green(bool self) internal pure returns (string memory) {
71
        return green(vm.toString(self));
72
    }
73

                            
                        
74
    function greenBytes(bytes memory self) internal pure returns (string memory) {
75
        return green(vm.toString(self));
76
    }
77

                            
                        
78
    function greenBytes32(bytes32 self) internal pure returns (string memory) {
79
        return green(vm.toString(self));
80
    }
81

                            
                        
82
    function yellow(string memory self) internal pure returns (string memory) {
83
        return styleConcat(YELLOW, self);
84
    }
85

                            
                        
86
    function yellow(uint256 self) internal pure returns (string memory) {
87
        return yellow(vm.toString(self));
88
    }
89

                            
                        
90
    function yellow(int256 self) internal pure returns (string memory) {
91
        return yellow(vm.toString(self));
92
    }
93

                            
                        
94
    function yellow(address self) internal pure returns (string memory) {
95
        return yellow(vm.toString(self));
96
    }
97

                            
                        
98
    function yellow(bool self) internal pure returns (string memory) {
99
        return yellow(vm.toString(self));
100
    }
101

                            
                        
102
    function yellowBytes(bytes memory self) internal pure returns (string memory) {
103
        return yellow(vm.toString(self));
104
    }
105

                            
                        
106
    function yellowBytes32(bytes32 self) internal pure returns (string memory) {
107
        return yellow(vm.toString(self));
108
    }
109

                            
                        
110
    function blue(string memory self) internal pure returns (string memory) {
111
        return styleConcat(BLUE, self);
112
    }
113

                            
                        
114
    function blue(uint256 self) internal pure returns (string memory) {
115
        return blue(vm.toString(self));
116
    }
117

                            
                        
118
    function blue(int256 self) internal pure returns (string memory) {
119
        return blue(vm.toString(self));
120
    }
121

                            
                        
122
    function blue(address self) internal pure returns (string memory) {
123
        return blue(vm.toString(self));
124
    }
125

                            
                        
126
    function blue(bool self) internal pure returns (string memory) {
127
        return blue(vm.toString(self));
128
    }
129

                            
                        
130
    function blueBytes(bytes memory self) internal pure returns (string memory) {
131
        return blue(vm.toString(self));
132
    }
133

                            
                        
134
    function blueBytes32(bytes32 self) internal pure returns (string memory) {
135
        return blue(vm.toString(self));
136
    }
137

                            
                        
138
    function magenta(string memory self) internal pure returns (string memory) {
139
        return styleConcat(MAGENTA, self);
140
    }
141

                            
                        
142
    function magenta(uint256 self) internal pure returns (string memory) {
143
        return magenta(vm.toString(self));
144
    }
145

                            
                        
146
    function magenta(int256 self) internal pure returns (string memory) {
147
        return magenta(vm.toString(self));
148
    }
149

                            
                        
150
    function magenta(address self) internal pure returns (string memory) {
151
        return magenta(vm.toString(self));
152
    }
153

                            
                        
154
    function magenta(bool self) internal pure returns (string memory) {
155
        return magenta(vm.toString(self));
156
    }
157

                            
                        
158
    function magentaBytes(bytes memory self) internal pure returns (string memory) {
159
        return magenta(vm.toString(self));
160
    }
161

                            
                        
162
    function magentaBytes32(bytes32 self) internal pure returns (string memory) {
163
        return magenta(vm.toString(self));
164
    }
165

                            
                        
166
    function cyan(string memory self) internal pure returns (string memory) {
167
        return styleConcat(CYAN, self);
168
    }
169

                            
                        
170
    function cyan(uint256 self) internal pure returns (string memory) {
171
        return cyan(vm.toString(self));
172
    }
173

                            
                        
174
    function cyan(int256 self) internal pure returns (string memory) {
175
        return cyan(vm.toString(self));
176
    }
177

                            
                        
178
    function cyan(address self) internal pure returns (string memory) {
179
        return cyan(vm.toString(self));
180
    }
181

                            
                        
182
    function cyan(bool self) internal pure returns (string memory) {
183
        return cyan(vm.toString(self));
184
    }
185

                            
                        
186
    function cyanBytes(bytes memory self) internal pure returns (string memory) {
187
        return cyan(vm.toString(self));
188
    }
189

                            
                        
190
    function cyanBytes32(bytes32 self) internal pure returns (string memory) {
191
        return cyan(vm.toString(self));
192
    }
193

                            
                        
194
    function bold(string memory self) internal pure returns (string memory) {
195
        return styleConcat(BOLD, self);
196
    }
197

                            
                        
198
    function bold(uint256 self) internal pure returns (string memory) {
199
        return bold(vm.toString(self));
200
    }
201

                            
                        
202
    function bold(int256 self) internal pure returns (string memory) {
203
        return bold(vm.toString(self));
204
    }
205

                            
                        
206
    function bold(address self) internal pure returns (string memory) {
207
        return bold(vm.toString(self));
208
    }
209

                            
                        
210
    function bold(bool self) internal pure returns (string memory) {
211
        return bold(vm.toString(self));
212
    }
213

                            
                        
214
    function boldBytes(bytes memory self) internal pure returns (string memory) {
215
        return bold(vm.toString(self));
216
    }
217

                            
                        
218
    function boldBytes32(bytes32 self) internal pure returns (string memory) {
219
        return bold(vm.toString(self));
220
    }
221

                            
                        
222
    function dim(string memory self) internal pure returns (string memory) {
223
        return styleConcat(DIM, self);
224
    }
225

                            
                        
226
    function dim(uint256 self) internal pure returns (string memory) {
227
        return dim(vm.toString(self));
228
    }
229

                            
                        
230
    function dim(int256 self) internal pure returns (string memory) {
231
        return dim(vm.toString(self));
232
    }
233

                            
                        
234
    function dim(address self) internal pure returns (string memory) {
235
        return dim(vm.toString(self));
236
    }
237

                            
                        
238
    function dim(bool self) internal pure returns (string memory) {
239
        return dim(vm.toString(self));
240
    }
241

                            
                        
242
    function dimBytes(bytes memory self) internal pure returns (string memory) {
243
        return dim(vm.toString(self));
244
    }
245

                            
                        
246
    function dimBytes32(bytes32 self) internal pure returns (string memory) {
247
        return dim(vm.toString(self));
248
    }
249

                            
                        
250
    function italic(string memory self) internal pure returns (string memory) {
251
        return styleConcat(ITALIC, self);
252
    }
253

                            
                        
254
    function italic(uint256 self) internal pure returns (string memory) {
255
        return italic(vm.toString(self));
256
    }
257

                            
                        
258
    function italic(int256 self) internal pure returns (string memory) {
259
        return italic(vm.toString(self));
260
    }
261

                            
                        
262
    function italic(address self) internal pure returns (string memory) {
263
        return italic(vm.toString(self));
264
    }
265

                            
                        
266
    function italic(bool self) internal pure returns (string memory) {
267
        return italic(vm.toString(self));
268
    }
269

                            
                        
270
    function italicBytes(bytes memory self) internal pure returns (string memory) {
271
        return italic(vm.toString(self));
272
    }
273

                            
                        
274
    function italicBytes32(bytes32 self) internal pure returns (string memory) {
275
        return italic(vm.toString(self));
276
    }
277

                            
                        
278
    function underline(string memory self) internal pure returns (string memory) {
279
        return styleConcat(UNDERLINE, self);
280
    }
281

                            
                        
282
    function underline(uint256 self) internal pure returns (string memory) {
283
        return underline(vm.toString(self));
284
    }
285

                            
                        
286
    function underline(int256 self) internal pure returns (string memory) {
287
        return underline(vm.toString(self));
288
    }
289

                            
                        
290
    function underline(address self) internal pure returns (string memory) {
291
        return underline(vm.toString(self));
292
    }
293

                            
                        
294
    function underline(bool self) internal pure returns (string memory) {
295
        return underline(vm.toString(self));
296
    }
297

                            
                        
298
    function underlineBytes(bytes memory self) internal pure returns (string memory) {
299
        return underline(vm.toString(self));
300
    }
301

                            
                        
302
    function underlineBytes32(bytes32 self) internal pure returns (string memory) {
303
        return underline(vm.toString(self));
304
    }
305

                            
                        
306
    function inverse(string memory self) internal pure returns (string memory) {
307
        return styleConcat(INVERSE, self);
308
    }
309

                            
                        
310
    function inverse(uint256 self) internal pure returns (string memory) {
311
        return inverse(vm.toString(self));
312
    }
313

                            
                        
314
    function inverse(int256 self) internal pure returns (string memory) {
315
        return inverse(vm.toString(self));
316
    }
317

                            
                        
318
    function inverse(address self) internal pure returns (string memory) {
319
        return inverse(vm.toString(self));
320
    }
321

                            
                        
322
    function inverse(bool self) internal pure returns (string memory) {
323
        return inverse(vm.toString(self));
324
    }
325

                            
                        
326
    function inverseBytes(bytes memory self) internal pure returns (string memory) {
327
        return inverse(vm.toString(self));
328
    }
329

                            
                        
330
    function inverseBytes32(bytes32 self) internal pure returns (string memory) {
331
        return inverse(vm.toString(self));
332
    }
333
}
334

                            
                        

Lines covered: 0 / 1 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.0 <0.9.0;
3

                            
                        
4
pragma experimental ABIEncoderV2;
5

                            
                        
6
import {VmSafe} from "./Vm.sol";
7

                            
                        
8
// Helpers for parsing and writing TOML files
9
// To parse:
10
// ```
11
// using stdToml for string;
12
// string memory toml = vm.readFile("<some_path>");
13
// toml.readUint("<json_path>");
14
// ```
15
// To write:
16
// ```
17
// using stdToml for string;
18
// string memory json = "json";
19
// json.serialize("a", uint256(123));
20
// string memory semiFinal = json.serialize("b", string("test"));
21
// string memory finalJson = json.serialize("c", semiFinal);
22
// finalJson.write("<some_path>");
23
// ```
24

                            
                        
25
library stdToml {
26
    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
27

                            
                        
28
    function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) {
29
        return vm.parseToml(toml, key);
30
    }
31

                            
                        
32
    function readUint(string memory toml, string memory key) internal pure returns (uint256) {
33
        return vm.parseTomlUint(toml, key);
34
    }
35

                            
                        
36
    function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) {
37
        return vm.parseTomlUintArray(toml, key);
38
    }
39

                            
                        
40
    function readInt(string memory toml, string memory key) internal pure returns (int256) {
41
        return vm.parseTomlInt(toml, key);
42
    }
43

                            
                        
44
    function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) {
45
        return vm.parseTomlIntArray(toml, key);
46
    }
47

                            
                        
48
    function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) {
49
        return vm.parseTomlBytes32(toml, key);
50
    }
51

                            
                        
52
    function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) {
53
        return vm.parseTomlBytes32Array(toml, key);
54
    }
55

                            
                        
56
    function readString(string memory toml, string memory key) internal pure returns (string memory) {
57
        return vm.parseTomlString(toml, key);
58
    }
59

                            
                        
60
    function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) {
61
        return vm.parseTomlStringArray(toml, key);
62
    }
63

                            
                        
64
    function readAddress(string memory toml, string memory key) internal pure returns (address) {
65
        return vm.parseTomlAddress(toml, key);
66
    }
67

                            
                        
68
    function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) {
69
        return vm.parseTomlAddressArray(toml, key);
70
    }
71

                            
                        
72
    function readBool(string memory toml, string memory key) internal pure returns (bool) {
73
        return vm.parseTomlBool(toml, key);
74
    }
75

                            
                        
76
    function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) {
77
        return vm.parseTomlBoolArray(toml, key);
78
    }
79

                            
                        
80
    function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) {
81
        return vm.parseTomlBytes(toml, key);
82
    }
83

                            
                        
84
    function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) {
85
        return vm.parseTomlBytesArray(toml, key);
86
    }
87

                            
                        
88
    function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
89
        return vm.serializeJson(jsonKey, rootObject);
90
    }
91

                            
                        
92
    function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
93
        return vm.serializeBool(jsonKey, key, value);
94
    }
95

                            
                        
96
    function serialize(string memory jsonKey, string memory key, bool[] memory value)
97
        internal
98
        returns (string memory)
99
    {
100
        return vm.serializeBool(jsonKey, key, value);
101
    }
102

                            
                        
103
    function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
104
        return vm.serializeUint(jsonKey, key, value);
105
    }
106

                            
                        
107
    function serialize(string memory jsonKey, string memory key, uint256[] memory value)
108
        internal
109
        returns (string memory)
110
    {
111
        return vm.serializeUint(jsonKey, key, value);
112
    }
113

                            
                        
114
    function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
115
        return vm.serializeInt(jsonKey, key, value);
116
    }
117

                            
                        
118
    function serialize(string memory jsonKey, string memory key, int256[] memory value)
119
        internal
120
        returns (string memory)
121
    {
122
        return vm.serializeInt(jsonKey, key, value);
123
    }
124

                            
                        
125
    function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
126
        return vm.serializeAddress(jsonKey, key, value);
127
    }
128

                            
                        
129
    function serialize(string memory jsonKey, string memory key, address[] memory value)
130
        internal
131
        returns (string memory)
132
    {
133
        return vm.serializeAddress(jsonKey, key, value);
134
    }
135

                            
                        
136
    function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
137
        return vm.serializeBytes32(jsonKey, key, value);
138
    }
139

                            
                        
140
    function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
141
        internal
142
        returns (string memory)
143
    {
144
        return vm.serializeBytes32(jsonKey, key, value);
145
    }
146

                            
                        
147
    function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
148
        return vm.serializeBytes(jsonKey, key, value);
149
    }
150

                            
                        
151
    function serialize(string memory jsonKey, string memory key, bytes[] memory value)
152
        internal
153
        returns (string memory)
154
    {
155
        return vm.serializeBytes(jsonKey, key, value);
156
    }
157

                            
                        
158
    function serialize(string memory jsonKey, string memory key, string memory value)
159
        internal
160
        returns (string memory)
161
    {
162
        return vm.serializeString(jsonKey, key, value);
163
    }
164

                            
                        
165
    function serialize(string memory jsonKey, string memory key, string[] memory value)
166
        internal
167
        returns (string memory)
168
    {
169
        return vm.serializeString(jsonKey, key, value);
170
    }
171

                            
                        
172
    function write(string memory jsonKey, string memory path) internal {
173
        vm.writeToml(jsonKey, path);
174
    }
175

                            
                        
176
    function write(string memory jsonKey, string memory path, string memory valueKey) internal {
177
        vm.writeToml(jsonKey, path, valueKey);
178
    }
179
}
180

                            
                        

Lines covered: 0 / 38 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
pragma experimental ABIEncoderV2;
5

                            
                        
6
import {IMulticall3} from "./interfaces/IMulticall3.sol";
7
import {MockERC20} from "./mocks/MockERC20.sol";
8
import {MockERC721} from "./mocks/MockERC721.sol";
9
import {VmSafe} from "./Vm.sol";
10

                            
                        
11
abstract contract StdUtils {
12
    /*//////////////////////////////////////////////////////////////////////////
13
                                     CONSTANTS
14
    //////////////////////////////////////////////////////////////////////////*/
15

                            
                        
16
    IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
17
    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
18
    address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
19
    uint256 private constant INT256_MIN_ABS =
20
        57896044618658097711785492504343953926634992332820282019728792003956564819968;
21
    uint256 private constant SECP256K1_ORDER =
22
        115792089237316195423570985008687907852837564279074904382605163141518161494337;
23
    uint256 private constant UINT256_MAX =
24
        115792089237316195423570985008687907853269984665640564039457584007913129639935;
25

                            
                        
26
    // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
27
    address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
28

                            
                        
29
    /*//////////////////////////////////////////////////////////////////////////
30
                                 INTERNAL FUNCTIONS
31
    //////////////////////////////////////////////////////////////////////////*/
32

                            
                        
33
    function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
34
        require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
35
        // If x is between min and max, return x directly. This is to ensure that dictionary values
36
        // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188
37
        if (x >= min && x <= max) return x;
38

                            
                        
39
        uint256 size = max - min + 1;
40

                            
                        
41
        // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.
42
        // This helps ensure coverage of the min/max values.
43
        if (x <= 3 && size > x) return min + x;
44
        if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);
45

                            
                        
46
        // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
47
        if (x > max) {
48
            uint256 diff = x - max;
49
            uint256 rem = diff % size;
50
            if (rem == 0) return max;
51
            result = min + rem - 1;
52
        } else if (x < min) {
53
            uint256 diff = min - x;
54
            uint256 rem = diff % size;
55
            if (rem == 0) return min;
56
            result = max - rem + 1;
57
        }
58
    }
59

                            
                        
60
    function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
61
        result = _bound(x, min, max);
62
        console2_log_StdUtils("Bound result", result);
63
    }
64

                            
                        
65
    function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
66
        require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
67

                            
                        
68
        // Shifting all int256 values to uint256 to use _bound function. The range of two types are:
69
        // int256 : -(2**255) ~ (2**255 - 1)
70
        // uint256:     0     ~ (2**256 - 1)
71
        // So, add 2**255, INT256_MIN_ABS to the integer values.
72
        //
73
        // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.
74
        // So, use `~uint256(x) + 1` instead.
75
        uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);
76
        uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);
77
        uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);
78

                            
                        
79
        uint256 y = _bound(_x, _min, _max);
80

                            
                        
81
        // To move it back to int256 value, subtract INT256_MIN_ABS at here.
82
        result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);
83
    }
84

                            
                        
85
    function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
86
        result = _bound(x, min, max);
87
        console2_log_StdUtils("Bound result", vm.toString(result));
88
    }
89

                            
                        
90
    function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) {
91
        result = _bound(privateKey, 1, SECP256K1_ORDER - 1);
92
    }
93

                            
                        
94
    function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
95
        require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
96
        return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
97
    }
98

                            
                        
99
    /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
100
    /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)
101
    function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
102
        console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
103
        return vm.computeCreateAddress(deployer, nonce);
104
    }
105

                            
                        
106
    function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
107
        internal
108
        pure
109
        virtual
110
        returns (address)
111
    {
112
        console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
113
        return vm.computeCreate2Address(salt, initcodeHash, deployer);
114
    }
115

                            
                        
116
    /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer
117
    function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {
118
        console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
119
        return vm.computeCreate2Address(salt, initCodeHash);
120
    }
121

                            
                        
122
    /// @dev returns an initialized mock ERC20 contract
123
    function deployMockERC20(string memory name, string memory symbol, uint8 decimals)
124
        internal
125
        returns (MockERC20 mock)
126
    {
127
        mock = new MockERC20();
128
        mock.initialize(name, symbol, decimals);
129
    }
130

                            
                        
131
    /// @dev returns an initialized mock ERC721 contract
132
    function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) {
133
        mock = new MockERC721();
134
        mock.initialize(name, symbol);
135
    }
136

                            
                        
137
    /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments
138
    /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
139
    function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {
140
        return hashInitCode(creationCode, "");
141
    }
142

                            
                        
143
    /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2
144
    /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
145
    /// @param args the ABI-encoded arguments to the constructor of C
146
    function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {
147
        return keccak256(abi.encodePacked(creationCode, args));
148
    }
149

                            
                        
150
    // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.
151
    function getTokenBalances(address token, address[] memory addresses)
152
        internal
153
        virtual
154
        returns (uint256[] memory balances)
155
    {
156
        uint256 tokenCodeSize;
157
        assembly {
158
            tokenCodeSize := extcodesize(token)
159
        }
160
        require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
161

                            
                        
162
        // ABI encode the aggregate call to Multicall3.
163
        uint256 length = addresses.length;
164
        IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);
165
        for (uint256 i = 0; i < length; ++i) {
166
            // 0x70a08231 = bytes4("balanceOf(address)"))
167
            calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
168
        }
169

                            
                        
170
        // Make the aggregate call.
171
        (, bytes[] memory returnData) = multicall.aggregate(calls);
172

                            
                        
173
        // ABI decode the return data and return the balances.
174
        balances = new uint256[](length);
175
        for (uint256 i = 0; i < length; ++i) {
176
            balances[i] = abi.decode(returnData[i], (uint256));
177
        }
178
    }
179

                            
                        
180
    /*//////////////////////////////////////////////////////////////////////////
181
                                 PRIVATE FUNCTIONS
182
    //////////////////////////////////////////////////////////////////////////*/
183

                            
                        
184
    function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
185
        return address(uint160(uint256(bytesValue)));
186
    }
187

                            
                        
188
    // This section is used to prevent the compilation of console, which shortens the compilation time when console is
189
    // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid
190
    // any breaking changes to function signatures.
191
    function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn)
192
        internal
193
        pure
194
        returns (function(bytes memory) internal pure fnOut)
195
    {
196
        assembly {
197
            fnOut := fnIn
198
        }
199
    }
200

                            
                        
201
    function _sendLogPayload(bytes memory payload) internal pure {
202
        _castLogPayloadViewToPure(_sendLogPayloadView)(payload);
203
    }
204

                            
                        
205
    function _sendLogPayloadView(bytes memory payload) private view {
206
        uint256 payloadLength = payload.length;
207
        address consoleAddress = CONSOLE2_ADDRESS;
208
        /// @solidity memory-safe-assembly
209
        assembly {
210
            let payloadStart := add(payload, 32)
211
            let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
212
        }
213
    }
214

                            
                        
215
    function console2_log_StdUtils(string memory p0) private pure {
216
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
217
    }
218

                            
                        
219
    function console2_log_StdUtils(string memory p0, uint256 p1) private pure {
220
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
221
    }
222

                            
                        
223
    function console2_log_StdUtils(string memory p0, string memory p1) private pure {
224
        _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
225
    }
226
}
227

                            
                        

Lines covered: 1 / 1 (100.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
pragma experimental ABIEncoderV2;
5

                            
                        
6
// 💬 ABOUT
7
// Forge Std's default Test.
8

                            
                        
9
// 🧩 MODULES
10
import {console} from "./console.sol";
11
import {console2} from "./console2.sol";
12
import {safeconsole} from "./safeconsole.sol";
13
import {StdAssertions} from "./StdAssertions.sol";
14
import {StdChains} from "./StdChains.sol";
15
import {StdCheats} from "./StdCheats.sol";
16
import {stdError} from "./StdError.sol";
17
import {StdInvariant} from "./StdInvariant.sol";
18
import {stdJson} from "./StdJson.sol";
19
import {stdMath} from "./StdMath.sol";
20
import {StdStorage, stdStorage} from "./StdStorage.sol";
21
import {StdStyle} from "./StdStyle.sol";
22
import {stdToml} from "./StdToml.sol";
23
import {StdUtils} from "./StdUtils.sol";
24
import {Vm} from "./Vm.sol";
25

                            
                        
26
// 📦 BOILERPLATE
27
import {TestBase} from "./Base.sol";
28

                            
                        
29
// ⭐️ TEST
30
abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils {
31
    // Note: IS_TEST() must return true.
32
√ 31
    bool public IS_TEST = true;
33
}
34

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// Automatically @generated by scripts/vm.py. Do not modify manually.
2

                            
                        
3
// SPDX-License-Identifier: MIT OR Apache-2.0
4
pragma solidity >=0.6.2 <0.9.0;
5
pragma experimental ABIEncoderV2;
6

                            
                        
7
/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
8
/// result in Script simulations differing from on-chain execution. It is recommended to only use
9
/// these cheats in scripts.
10
interface VmSafe {
11
    /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`.
12
    enum CallerMode {
13
        // No caller modification is currently active.
14
        None,
15
        // A one time broadcast triggered by a `vm.broadcast()` call is currently active.
16
        Broadcast,
17
        // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active.
18
        RecurrentBroadcast,
19
        // A one time prank triggered by a `vm.prank()` call is currently active.
20
        Prank,
21
        // A recurrent prank triggered by a `vm.startPrank()` call is currently active.
22
        RecurrentPrank
23
    }
24

                            
                        
25
    /// The kind of account access that occurred.
26
    enum AccountAccessKind {
27
        // The account was called.
28
        Call,
29
        // The account was called via delegatecall.
30
        DelegateCall,
31
        // The account was called via callcode.
32
        CallCode,
33
        // The account was called via staticcall.
34
        StaticCall,
35
        // The account was created.
36
        Create,
37
        // The account was selfdestructed.
38
        SelfDestruct,
39
        // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess).
40
        Resume,
41
        // The account's balance was read.
42
        Balance,
43
        // The account's codesize was read.
44
        Extcodesize,
45
        // The account's codehash was read.
46
        Extcodehash,
47
        // The account's code was copied.
48
        Extcodecopy
49
    }
50

                            
                        
51
    /// Forge execution contexts.
52
    enum ForgeContext {
53
        // Test group execution context (test, coverage or snapshot).
54
        TestGroup,
55
        // `forge test` execution context.
56
        Test,
57
        // `forge coverage` execution context.
58
        Coverage,
59
        // `forge snapshot` execution context.
60
        Snapshot,
61
        // Script group execution context (dry run, broadcast or resume).
62
        ScriptGroup,
63
        // `forge script` execution context.
64
        ScriptDryRun,
65
        // `forge script --broadcast` execution context.
66
        ScriptBroadcast,
67
        // `forge script --resume` execution context.
68
        ScriptResume,
69
        // Unknown `forge` execution context.
70
        Unknown
71
    }
72

                            
                        
73
    /// An Ethereum log. Returned by `getRecordedLogs`.
74
    struct Log {
75
        // The topics of the log, including the signature, if any.
76
        bytes32[] topics;
77
        // The raw data of the log.
78
        bytes data;
79
        // The address of the log's emitter.
80
        address emitter;
81
    }
82

                            
                        
83
    /// An RPC URL and its alias. Returned by `rpcUrlStructs`.
84
    struct Rpc {
85
        // The alias of the RPC URL.
86
        string key;
87
        // The RPC URL.
88
        string url;
89
    }
90

                            
                        
91
    /// An RPC log object. Returned by `eth_getLogs`.
92
    struct EthGetLogs {
93
        // The address of the log's emitter.
94
        address emitter;
95
        // The topics of the log, including the signature, if any.
96
        bytes32[] topics;
97
        // The raw data of the log.
98
        bytes data;
99
        // The block hash.
100
        bytes32 blockHash;
101
        // The block number.
102
        uint64 blockNumber;
103
        // The transaction hash.
104
        bytes32 transactionHash;
105
        // The transaction index in the block.
106
        uint64 transactionIndex;
107
        // The log index.
108
        uint256 logIndex;
109
        // Whether the log was removed.
110
        bool removed;
111
    }
112

                            
                        
113
    /// A single entry in a directory listing. Returned by `readDir`.
114
    struct DirEntry {
115
        // The error message, if any.
116
        string errorMessage;
117
        // The path of the entry.
118
        string path;
119
        // The depth of the entry.
120
        uint64 depth;
121
        // Whether the entry is a directory.
122
        bool isDir;
123
        // Whether the entry is a symlink.
124
        bool isSymlink;
125
    }
126

                            
                        
127
    /// Metadata information about a file.
128
    /// This structure is returned from the `fsMetadata` function and represents known
129
    /// metadata about a file such as its permissions, size, modification
130
    /// times, etc.
131
    struct FsMetadata {
132
        // True if this metadata is for a directory.
133
        bool isDir;
134
        // True if this metadata is for a symlink.
135
        bool isSymlink;
136
        // The size of the file, in bytes, this metadata is for.
137
        uint256 length;
138
        // True if this metadata is for a readonly (unwritable) file.
139
        bool readOnly;
140
        // The last modification time listed in this metadata.
141
        uint256 modified;
142
        // The last access time of this metadata.
143
        uint256 accessed;
144
        // The creation time listed in this metadata.
145
        uint256 created;
146
    }
147

                            
                        
148
    /// A wallet with a public and private key.
149
    struct Wallet {
150
        // The wallet's address.
151
        address addr;
152
        // The wallet's public key `X`.
153
        uint256 publicKeyX;
154
        // The wallet's public key `Y`.
155
        uint256 publicKeyY;
156
        // The wallet's private key.
157
        uint256 privateKey;
158
    }
159

                            
                        
160
    /// The result of a `tryFfi` call.
161
    struct FfiResult {
162
        // The exit code of the call.
163
        int32 exitCode;
164
        // The optionally hex-decoded `stdout` data.
165
        bytes stdout;
166
        // The `stderr` data.
167
        bytes stderr;
168
    }
169

                            
                        
170
    /// Information on the chain and fork.
171
    struct ChainInfo {
172
        // The fork identifier. Set to zero if no fork is active.
173
        uint256 forkId;
174
        // The chain ID of the current fork.
175
        uint256 chainId;
176
    }
177

                            
                        
178
    /// The result of a `stopAndReturnStateDiff` call.
179
    struct AccountAccess {
180
        // The chain and fork the access occurred.
181
        ChainInfo chainInfo;
182
        // The kind of account access that determines what the account is.
183
        // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee.
184
        // If kind is Create, then the account is the newly created account.
185
        // If kind is SelfDestruct, then the account is the selfdestruct recipient.
186
        // If kind is a Resume, then account represents a account context that has resumed.
187
        AccountAccessKind kind;
188
        // The account that was accessed.
189
        // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT.
190
        address account;
191
        // What accessed the account.
192
        address accessor;
193
        // If the account was initialized or empty prior to the access.
194
        // An account is considered initialized if it has code, a
195
        // non-zero nonce, or a non-zero balance.
196
        bool initialized;
197
        // The previous balance of the accessed account.
198
        uint256 oldBalance;
199
        // The potential new balance of the accessed account.
200
        // That is, all balance changes are recorded here, even if reverts occurred.
201
        uint256 newBalance;
202
        // Code of the account deployed by CREATE.
203
        bytes deployedCode;
204
        // Value passed along with the account access
205
        uint256 value;
206
        // Input data provided to the CREATE or CALL
207
        bytes data;
208
        // If this access reverted in either the current or parent context.
209
        bool reverted;
210
        // An ordered list of storage accesses made during an account access operation.
211
        StorageAccess[] storageAccesses;
212
        // Call depth traversed during the recording of state differences
213
        uint64 depth;
214
    }
215

                            
                        
216
    /// The storage accessed during an `AccountAccess`.
217
    struct StorageAccess {
218
        // The account whose storage was accessed.
219
        address account;
220
        // The slot that was accessed.
221
        bytes32 slot;
222
        // If the access was a write.
223
        bool isWrite;
224
        // The previous value of the slot.
225
        bytes32 previousValue;
226
        // The new value of the slot.
227
        bytes32 newValue;
228
        // If the access was reverted.
229
        bool reverted;
230
    }
231

                            
                        
232
    /// Gas used. Returned by `lastCallGas`.
233
    struct Gas {
234
        // The gas limit of the call.
235
        uint64 gasLimit;
236
        // The total gas used.
237
        uint64 gasTotalUsed;
238
        // DEPRECATED: The amount of gas used for memory expansion. Ref: <https://github.com/foundry-rs/foundry/pull/7934#pullrequestreview-2069236939>
239
        uint64 gasMemoryUsed;
240
        // The amount of gas refunded.
241
        int64 gasRefunded;
242
        // The amount of gas remaining.
243
        uint64 gasRemaining;
244
    }
245

                            
                        
246
    // ======== Crypto ========
247

                            
                        
248
    /// Derives a private key from the name, labels the account with that name, and returns the wallet.
249
    function createWallet(string calldata walletLabel) external returns (Wallet memory wallet);
250

                            
                        
251
    /// Generates a wallet from the private key and returns the wallet.
252
    function createWallet(uint256 privateKey) external returns (Wallet memory wallet);
253

                            
                        
254
    /// Generates a wallet from the private key, labels the account with that name, and returns the wallet.
255
    function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet);
256

                            
                        
257
    /// Derive a private key from a provided mnenomic string (or mnenomic file path)
258
    /// at the derivation path `m/44'/60'/0'/0/{index}`.
259
    function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);
260

                            
                        
261
    /// Derive a private key from a provided mnenomic string (or mnenomic file path)
262
    /// at `{derivationPath}{index}`.
263
    function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)
264
        external
265
        pure
266
        returns (uint256 privateKey);
267

                            
                        
268
    /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language
269
    /// at the derivation path `m/44'/60'/0'/0/{index}`.
270
    function deriveKey(string calldata mnemonic, uint32 index, string calldata language)
271
        external
272
        pure
273
        returns (uint256 privateKey);
274

                            
                        
275
    /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language
276
    /// at `{derivationPath}{index}`.
277
    function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language)
278
        external
279
        pure
280
        returns (uint256 privateKey);
281

                            
                        
282
    /// Adds a private key to the local forge wallet and returns the address.
283
    function rememberKey(uint256 privateKey) external returns (address keyAddr);
284

                            
                        
285
    /// Signs data with a `Wallet`.
286
    /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
287
    /// signature's `s` value, and the recovery id `v` in a single bytes32.
288
    /// This format reduces the signature size from 65 to 64 bytes.
289
    function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs);
290

                            
                        
291
    /// Signs `digest` with `privateKey` using the secp256k1 curve.
292
    /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
293
    /// signature's `s` value, and the recovery id `v` in a single bytes32.
294
    /// This format reduces the signature size from 65 to 64 bytes.
295
    function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
296

                            
                        
297
    /// Signs `digest` with signer provided to script using the secp256k1 curve.
298
    /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
299
    /// signature's `s` value, and the recovery id `v` in a single bytes32.
300
    /// This format reduces the signature size from 65 to 64 bytes.
301
    /// If `--sender` is provided, the signer with provided address is used, otherwise,
302
    /// if exactly one signer is provided to the script, that signer is used.
303
    /// Raises error if signer passed through `--sender` does not match any unlocked signers or
304
    /// if `--sender` is not provided and not exactly one signer is passed to the script.
305
    function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
306

                            
                        
307
    /// Signs `digest` with signer provided to script using the secp256k1 curve.
308
    /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
309
    /// signature's `s` value, and the recovery id `v` in a single bytes32.
310
    /// This format reduces the signature size from 65 to 64 bytes.
311
    /// Raises error if none of the signers passed into the script have provided address.
312
    function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
313

                            
                        
314
    /// Signs `digest` with `privateKey` using the secp256r1 curve.
315
    function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s);
316

                            
                        
317
    /// Signs data with a `Wallet`.
318
    function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);
319

                            
                        
320
    /// Signs `digest` with `privateKey` using the secp256k1 curve.
321
    function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
322

                            
                        
323
    /// Signs `digest` with signer provided to script using the secp256k1 curve.
324
    /// If `--sender` is provided, the signer with provided address is used, otherwise,
325
    /// if exactly one signer is provided to the script, that signer is used.
326
    /// Raises error if signer passed through `--sender` does not match any unlocked signers or
327
    /// if `--sender` is not provided and not exactly one signer is passed to the script.
328
    function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
329

                            
                        
330
    /// Signs `digest` with signer provided to script using the secp256k1 curve.
331
    /// Raises error if none of the signers passed into the script have provided address.
332
    function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
333

                            
                        
334
    // ======== Environment ========
335

                            
                        
336
    /// Gets the environment variable `name` and parses it as `address`.
337
    /// Reverts if the variable was not found or could not be parsed.
338
    function envAddress(string calldata name) external view returns (address value);
339

                            
                        
340
    /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
341
    /// Reverts if the variable was not found or could not be parsed.
342
    function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);
343

                            
                        
344
    /// Gets the environment variable `name` and parses it as `bool`.
345
    /// Reverts if the variable was not found or could not be parsed.
346
    function envBool(string calldata name) external view returns (bool value);
347

                            
                        
348
    /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
349
    /// Reverts if the variable was not found or could not be parsed.
350
    function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);
351

                            
                        
352
    /// Gets the environment variable `name` and parses it as `bytes32`.
353
    /// Reverts if the variable was not found or could not be parsed.
354
    function envBytes32(string calldata name) external view returns (bytes32 value);
355

                            
                        
356
    /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
357
    /// Reverts if the variable was not found or could not be parsed.
358
    function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);
359

                            
                        
360
    /// Gets the environment variable `name` and parses it as `bytes`.
361
    /// Reverts if the variable was not found or could not be parsed.
362
    function envBytes(string calldata name) external view returns (bytes memory value);
363

                            
                        
364
    /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
365
    /// Reverts if the variable was not found or could not be parsed.
366
    function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);
367

                            
                        
368
    /// Gets the environment variable `name` and returns true if it exists, else returns false.
369
    function envExists(string calldata name) external view returns (bool result);
370

                            
                        
371
    /// Gets the environment variable `name` and parses it as `int256`.
372
    /// Reverts if the variable was not found or could not be parsed.
373
    function envInt(string calldata name) external view returns (int256 value);
374

                            
                        
375
    /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
376
    /// Reverts if the variable was not found or could not be parsed.
377
    function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);
378

                            
                        
379
    /// Gets the environment variable `name` and parses it as `bool`.
380
    /// Reverts if the variable could not be parsed.
381
    /// Returns `defaultValue` if the variable was not found.
382
    function envOr(string calldata name, bool defaultValue) external view returns (bool value);
383

                            
                        
384
    /// Gets the environment variable `name` and parses it as `uint256`.
385
    /// Reverts if the variable could not be parsed.
386
    /// Returns `defaultValue` if the variable was not found.
387
    function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value);
388

                            
                        
389
    /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
390
    /// Reverts if the variable could not be parsed.
391
    /// Returns `defaultValue` if the variable was not found.
392
    function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
393
        external
394
        view
395
        returns (address[] memory value);
396

                            
                        
397
    /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
398
    /// Reverts if the variable could not be parsed.
399
    /// Returns `defaultValue` if the variable was not found.
400
    function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
401
        external
402
        view
403
        returns (bytes32[] memory value);
404

                            
                        
405
    /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
406
    /// Reverts if the variable could not be parsed.
407
    /// Returns `defaultValue` if the variable was not found.
408
    function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
409
        external
410
        view
411
        returns (string[] memory value);
412

                            
                        
413
    /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
414
    /// Reverts if the variable could not be parsed.
415
    /// Returns `defaultValue` if the variable was not found.
416
    function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
417
        external
418
        view
419
        returns (bytes[] memory value);
420

                            
                        
421
    /// Gets the environment variable `name` and parses it as `int256`.
422
    /// Reverts if the variable could not be parsed.
423
    /// Returns `defaultValue` if the variable was not found.
424
    function envOr(string calldata name, int256 defaultValue) external view returns (int256 value);
425

                            
                        
426
    /// Gets the environment variable `name` and parses it as `address`.
427
    /// Reverts if the variable could not be parsed.
428
    /// Returns `defaultValue` if the variable was not found.
429
    function envOr(string calldata name, address defaultValue) external view returns (address value);
430

                            
                        
431
    /// Gets the environment variable `name` and parses it as `bytes32`.
432
    /// Reverts if the variable could not be parsed.
433
    /// Returns `defaultValue` if the variable was not found.
434
    function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value);
435

                            
                        
436
    /// Gets the environment variable `name` and parses it as `string`.
437
    /// Reverts if the variable could not be parsed.
438
    /// Returns `defaultValue` if the variable was not found.
439
    function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value);
440

                            
                        
441
    /// Gets the environment variable `name` and parses it as `bytes`.
442
    /// Reverts if the variable could not be parsed.
443
    /// Returns `defaultValue` if the variable was not found.
444
    function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value);
445

                            
                        
446
    /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
447
    /// Reverts if the variable could not be parsed.
448
    /// Returns `defaultValue` if the variable was not found.
449
    function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
450
        external
451
        view
452
        returns (bool[] memory value);
453

                            
                        
454
    /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
455
    /// Reverts if the variable could not be parsed.
456
    /// Returns `defaultValue` if the variable was not found.
457
    function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
458
        external
459
        view
460
        returns (uint256[] memory value);
461

                            
                        
462
    /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
463
    /// Reverts if the variable could not be parsed.
464
    /// Returns `defaultValue` if the variable was not found.
465
    function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
466
        external
467
        view
468
        returns (int256[] memory value);
469

                            
                        
470
    /// Gets the environment variable `name` and parses it as `string`.
471
    /// Reverts if the variable was not found or could not be parsed.
472
    function envString(string calldata name) external view returns (string memory value);
473

                            
                        
474
    /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
475
    /// Reverts if the variable was not found or could not be parsed.
476
    function envString(string calldata name, string calldata delim) external view returns (string[] memory value);
477

                            
                        
478
    /// Gets the environment variable `name` and parses it as `uint256`.
479
    /// Reverts if the variable was not found or could not be parsed.
480
    function envUint(string calldata name) external view returns (uint256 value);
481

                            
                        
482
    /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
483
    /// Reverts if the variable was not found or could not be parsed.
484
    function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);
485

                            
                        
486
    /// Returns true if `forge` command was executed in given context.
487
    function isContext(ForgeContext context) external view returns (bool result);
488

                            
                        
489
    /// Sets environment variables.
490
    function setEnv(string calldata name, string calldata value) external;
491

                            
                        
492
    // ======== EVM ========
493

                            
                        
494
    /// Gets all accessed reads and write slot from a `vm.record` session, for a given address.
495
    function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);
496

                            
                        
497
    /// Gets the address for a given private key.
498
    function addr(uint256 privateKey) external pure returns (address keyAddr);
499

                            
                        
500
    /// Gets all the logs according to specified filter.
501
    function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics)
502
        external
503
        returns (EthGetLogs[] memory logs);
504

                            
                        
505
    /// Gets the current `block.blobbasefee`.
506
    /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction,
507
    /// and as a result will get optimized out by the compiler.
508
    /// See https://github.com/foundry-rs/foundry/issues/6180
509
    function getBlobBaseFee() external view returns (uint256 blobBaseFee);
510

                            
                        
511
    /// Gets the current `block.number`.
512
    /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction,
513
    /// and as a result will get optimized out by the compiler.
514
    /// See https://github.com/foundry-rs/foundry/issues/6180
515
    function getBlockNumber() external view returns (uint256 height);
516

                            
                        
517
    /// Gets the current `block.timestamp`.
518
    /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction,
519
    /// and as a result will get optimized out by the compiler.
520
    /// See https://github.com/foundry-rs/foundry/issues/6180
521
    function getBlockTimestamp() external view returns (uint256 timestamp);
522

                            
                        
523
    /// Gets the map key and parent of a mapping at a given slot, for a given address.
524
    function getMappingKeyAndParentOf(address target, bytes32 elementSlot)
525
        external
526
        returns (bool found, bytes32 key, bytes32 parent);
527

                            
                        
528
    /// Gets the number of elements in the mapping at the given slot, for a given address.
529
    function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length);
530

                            
                        
531
    /// Gets the elements at index idx of the mapping at the given slot, for a given address. The
532
    /// index must be less than the length of the mapping (i.e. the number of keys in the mapping).
533
    function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value);
534

                            
                        
535
    /// Gets the nonce of an account.
536
    function getNonce(address account) external view returns (uint64 nonce);
537

                            
                        
538
    /// Get the nonce of a `Wallet`.
539
    function getNonce(Wallet calldata wallet) external returns (uint64 nonce);
540

                            
                        
541
    /// Gets all the recorded logs.
542
    function getRecordedLogs() external returns (Log[] memory logs);
543

                            
                        
544
    /// Gets the gas used in the last call.
545
    function lastCallGas() external view returns (Gas memory gas);
546

                            
                        
547
    /// Loads a storage slot from an address.
548
    function load(address target, bytes32 slot) external view returns (bytes32 data);
549

                            
                        
550
    /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.
551
    function pauseGasMetering() external;
552

                            
                        
553
    /// Records all storage reads and writes.
554
    function record() external;
555

                            
                        
556
    /// Record all the transaction logs.
557
    function recordLogs() external;
558

                            
                        
559
    /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on.
560
    function resumeGasMetering() external;
561

                            
                        
562
    /// Performs an Ethereum JSON-RPC request to the current fork URL.
563
    function rpc(string calldata method, string calldata params) external returns (bytes memory data);
564

                            
                        
565
    /// Performs an Ethereum JSON-RPC request to the given endpoint.
566
    function rpc(string calldata urlOrAlias, string calldata method, string calldata params)
567
        external
568
        returns (bytes memory data);
569

                            
                        
570
    /// Starts recording all map SSTOREs for later retrieval.
571
    function startMappingRecording() external;
572

                            
                        
573
    /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
574
    /// along with the context of the calls
575
    function startStateDiffRecording() external;
576

                            
                        
577
    /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session.
578
    function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses);
579

                            
                        
580
    /// Stops recording all map SSTOREs for later retrieval and clears the recorded data.
581
    function stopMappingRecording() external;
582

                            
                        
583
    // ======== Filesystem ========
584

                            
                        
585
    /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
586
    /// `path` is relative to the project root.
587
    function closeFile(string calldata path) external;
588

                            
                        
589
    /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`.
590
    /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`.
591
    /// Both `from` and `to` are relative to the project root.
592
    function copyFile(string calldata from, string calldata to) external returns (uint64 copied);
593

                            
                        
594
    /// Creates a new, empty directory at the provided path.
595
    /// This cheatcode will revert in the following situations, but is not limited to just these cases:
596
    /// - User lacks permissions to modify `path`.
597
    /// - A parent of the given path doesn't exist and `recursive` is false.
598
    /// - `path` already exists and `recursive` is false.
599
    /// `path` is relative to the project root.
600
    function createDir(string calldata path, bool recursive) external;
601

                            
                        
602
    /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
603
    /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
604
    function deployCode(string calldata artifactPath) external returns (address deployedAddress);
605

                            
                        
606
    /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
607
    /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
608
    /// Additionaly accepts abi-encoded constructor arguments.
609
    function deployCode(string calldata artifactPath, bytes calldata constructorArgs)
610
        external
611
        returns (address deployedAddress);
612

                            
                        
613
    /// Returns true if the given path points to an existing entity, else returns false.
614
    function exists(string calldata path) external returns (bool result);
615

                            
                        
616
    /// Performs a foreign function call via the terminal.
617
    function ffi(string[] calldata commandInput) external returns (bytes memory result);
618

                            
                        
619
    /// Given a path, query the file system to get information about a file, directory, etc.
620
    function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata);
621

                            
                        
622
    /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the
623
    /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
624
    function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);
625

                            
                        
626
    /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the
627
    /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.
628
    function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);
629

                            
                        
630
    /// Returns true if the path exists on disk and is pointing at a directory, else returns false.
631
    function isDir(string calldata path) external returns (bool result);
632

                            
                        
633
    /// Returns true if the path exists on disk and is pointing at a regular file, else returns false.
634
    function isFile(string calldata path) external returns (bool result);
635

                            
                        
636
    /// Get the path of the current project root.
637
    function projectRoot() external view returns (string memory path);
638

                            
                        
639
    /// Prompts the user for a string value in the terminal.
640
    function prompt(string calldata promptText) external returns (string memory input);
641

                            
                        
642
    /// Prompts the user for an address in the terminal.
643
    function promptAddress(string calldata promptText) external returns (address);
644

                            
                        
645
    /// Prompts the user for a hidden string value in the terminal.
646
    function promptSecret(string calldata promptText) external returns (string memory input);
647

                            
                        
648
    /// Prompts the user for hidden uint256 in the terminal (usually pk).
649
    function promptSecretUint(string calldata promptText) external returns (uint256);
650

                            
                        
651
    /// Prompts the user for uint256 in the terminal.
652
    function promptUint(string calldata promptText) external returns (uint256);
653

                            
                        
654
    /// Reads the directory at the given path recursively, up to `maxDepth`.
655
    /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned.
656
    /// Follows symbolic links if `followLinks` is true.
657
    function readDir(string calldata path) external view returns (DirEntry[] memory entries);
658

                            
                        
659
    /// See `readDir(string)`.
660
    function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries);
661

                            
                        
662
    /// See `readDir(string)`.
663
    function readDir(string calldata path, uint64 maxDepth, bool followLinks)
664
        external
665
        view
666
        returns (DirEntry[] memory entries);
667

                            
                        
668
    /// Reads the entire content of file to string. `path` is relative to the project root.
669
    function readFile(string calldata path) external view returns (string memory data);
670

                            
                        
671
    /// Reads the entire content of file as binary. `path` is relative to the project root.
672
    function readFileBinary(string calldata path) external view returns (bytes memory data);
673

                            
                        
674
    /// Reads next line of file to string.
675
    function readLine(string calldata path) external view returns (string memory line);
676

                            
                        
677
    /// Reads a symbolic link, returning the path that the link points to.
678
    /// This cheatcode will revert in the following situations, but is not limited to just these cases:
679
    /// - `path` is not a symbolic link.
680
    /// - `path` does not exist.
681
    function readLink(string calldata linkPath) external view returns (string memory targetPath);
682

                            
                        
683
    /// Removes a directory at the provided path.
684
    /// This cheatcode will revert in the following situations, but is not limited to just these cases:
685
    /// - `path` doesn't exist.
686
    /// - `path` isn't a directory.
687
    /// - User lacks permissions to modify `path`.
688
    /// - The directory is not empty and `recursive` is false.
689
    /// `path` is relative to the project root.
690
    function removeDir(string calldata path, bool recursive) external;
691

                            
                        
692
    /// Removes a file from the filesystem.
693
    /// This cheatcode will revert in the following situations, but is not limited to just these cases:
694
    /// - `path` points to a directory.
695
    /// - The file doesn't exist.
696
    /// - The user lacks permissions to remove the file.
697
    /// `path` is relative to the project root.
698
    function removeFile(string calldata path) external;
699

                            
                        
700
    /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr.
701
    function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result);
702

                            
                        
703
    /// Returns the time since unix epoch in milliseconds.
704
    function unixTime() external returns (uint256 milliseconds);
705

                            
                        
706
    /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
707
    /// `path` is relative to the project root.
708
    function writeFile(string calldata path, string calldata data) external;
709

                            
                        
710
    /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.
711
    /// `path` is relative to the project root.
712
    function writeFileBinary(string calldata path, bytes calldata data) external;
713

                            
                        
714
    /// Writes line to file, creating a file if it does not exist.
715
    /// `path` is relative to the project root.
716
    function writeLine(string calldata path, string calldata data) external;
717

                            
                        
718
    // ======== JSON ========
719

                            
                        
720
    /// Checks if `key` exists in a JSON object
721
    /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions.
722
    function keyExists(string calldata json, string calldata key) external view returns (bool);
723

                            
                        
724
    /// Checks if `key` exists in a JSON object.
725
    function keyExistsJson(string calldata json, string calldata key) external view returns (bool);
726

                            
                        
727
    /// Parses a string of JSON data at `key` and coerces it to `address`.
728
    function parseJsonAddress(string calldata json, string calldata key) external pure returns (address);
729

                            
                        
730
    /// Parses a string of JSON data at `key` and coerces it to `address[]`.
731
    function parseJsonAddressArray(string calldata json, string calldata key)
732
        external
733
        pure
734
        returns (address[] memory);
735

                            
                        
736
    /// Parses a string of JSON data at `key` and coerces it to `bool`.
737
    function parseJsonBool(string calldata json, string calldata key) external pure returns (bool);
738

                            
                        
739
    /// Parses a string of JSON data at `key` and coerces it to `bool[]`.
740
    function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory);
741

                            
                        
742
    /// Parses a string of JSON data at `key` and coerces it to `bytes`.
743
    function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory);
744

                            
                        
745
    /// Parses a string of JSON data at `key` and coerces it to `bytes32`.
746
    function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32);
747

                            
                        
748
    /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`.
749
    function parseJsonBytes32Array(string calldata json, string calldata key)
750
        external
751
        pure
752
        returns (bytes32[] memory);
753

                            
                        
754
    /// Parses a string of JSON data at `key` and coerces it to `bytes[]`.
755
    function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory);
756

                            
                        
757
    /// Parses a string of JSON data at `key` and coerces it to `int256`.
758
    function parseJsonInt(string calldata json, string calldata key) external pure returns (int256);
759

                            
                        
760
    /// Parses a string of JSON data at `key` and coerces it to `int256[]`.
761
    function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory);
762

                            
                        
763
    /// Returns an array of all the keys in a JSON object.
764
    function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys);
765

                            
                        
766
    /// Parses a string of JSON data at `key` and coerces it to `string`.
767
    function parseJsonString(string calldata json, string calldata key) external pure returns (string memory);
768

                            
                        
769
    /// Parses a string of JSON data at `key` and coerces it to `string[]`.
770
    function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory);
771

                            
                        
772
    /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`.
773
    function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription)
774
        external
775
        pure
776
        returns (bytes memory);
777

                            
                        
778
    /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`.
779
    function parseJsonType(string calldata json, string calldata typeDescription)
780
        external
781
        pure
782
        returns (bytes memory);
783

                            
                        
784
    /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`.
785
    function parseJsonType(string calldata json, string calldata key, string calldata typeDescription)
786
        external
787
        pure
788
        returns (bytes memory);
789

                            
                        
790
    /// Parses a string of JSON data at `key` and coerces it to `uint256`.
791
    function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256);
792

                            
                        
793
    /// Parses a string of JSON data at `key` and coerces it to `uint256[]`.
794
    function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory);
795

                            
                        
796
    /// ABI-encodes a JSON object.
797
    function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);
798

                            
                        
799
    /// ABI-encodes a JSON object at `key`.
800
    function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);
801

                            
                        
802
    /// See `serializeJson`.
803
    function serializeAddress(string calldata objectKey, string calldata valueKey, address value)
804
        external
805
        returns (string memory json);
806

                            
                        
807
    /// See `serializeJson`.
808
    function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)
809
        external
810
        returns (string memory json);
811

                            
                        
812
    /// See `serializeJson`.
813
    function serializeBool(string calldata objectKey, string calldata valueKey, bool value)
814
        external
815
        returns (string memory json);
816

                            
                        
817
    /// See `serializeJson`.
818
    function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)
819
        external
820
        returns (string memory json);
821

                            
                        
822
    /// See `serializeJson`.
823
    function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)
824
        external
825
        returns (string memory json);
826

                            
                        
827
    /// See `serializeJson`.
828
    function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)
829
        external
830
        returns (string memory json);
831

                            
                        
832
    /// See `serializeJson`.
833
    function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)
834
        external
835
        returns (string memory json);
836

                            
                        
837
    /// See `serializeJson`.
838
    function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)
839
        external
840
        returns (string memory json);
841

                            
                        
842
    /// See `serializeJson`.
843
    function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)
844
        external
845
        returns (string memory json);
846

                            
                        
847
    /// See `serializeJson`.
848
    function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)
849
        external
850
        returns (string memory json);
851

                            
                        
852
    /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file.
853
    /// Returns the stringified version of the specific JSON file up to that moment.
854
    function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json);
855

                            
                        
856
    /// See `serializeJson`.
857
    function serializeJsonType(string calldata typeDescription, bytes calldata value)
858
        external
859
        pure
860
        returns (string memory json);
861

                            
                        
862
    /// See `serializeJson`.
863
    function serializeJsonType(
864
        string calldata objectKey,
865
        string calldata valueKey,
866
        string calldata typeDescription,
867
        bytes calldata value
868
    ) external returns (string memory json);
869

                            
                        
870
    /// See `serializeJson`.
871
    function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)
872
        external
873
        returns (string memory json);
874

                            
                        
875
    /// See `serializeJson`.
876
    function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)
877
        external
878
        returns (string memory json);
879

                            
                        
880
    /// See `serializeJson`.
881
    function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value)
882
        external
883
        returns (string memory json);
884

                            
                        
885
    /// See `serializeJson`.
886
    function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)
887
        external
888
        returns (string memory json);
889

                            
                        
890
    /// See `serializeJson`.
891
    function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)
892
        external
893
        returns (string memory json);
894

                            
                        
895
    /// Write a serialized JSON object to a file. If the file exists, it will be overwritten.
896
    function writeJson(string calldata json, string calldata path) external;
897

                            
                        
898
    /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key.>
899
    /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing.
900
    function writeJson(string calldata json, string calldata path, string calldata valueKey) external;
901

                            
                        
902
    // ======== Scripting ========
903

                            
                        
904
    /// Takes a signed transaction and broadcasts it to the network.
905
    function broadcastRawTransaction(bytes calldata data) external;
906

                            
                        
907
    /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain.
908
    /// Broadcasting address is determined by checking the following in order:
909
    /// 1. If `--sender` argument was provided, that address is used.
910
    /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
911
    /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
912
    function broadcast() external;
913

                            
                        
914
    /// Has the next call (at this call depth only) create a transaction with the address provided
915
    /// as the sender that can later be signed and sent onchain.
916
    function broadcast(address signer) external;
917

                            
                        
918
    /// Has the next call (at this call depth only) create a transaction with the private key
919
    /// provided as the sender that can later be signed and sent onchain.
920
    function broadcast(uint256 privateKey) external;
921

                            
                        
922
    /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain.
923
    /// Broadcasting address is determined by checking the following in order:
924
    /// 1. If `--sender` argument was provided, that address is used.
925
    /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
926
    /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
927
    function startBroadcast() external;
928

                            
                        
929
    /// Has all subsequent calls (at this call depth only) create transactions with the address
930
    /// provided that can later be signed and sent onchain.
931
    function startBroadcast(address signer) external;
932

                            
                        
933
    /// Has all subsequent calls (at this call depth only) create transactions with the private key
934
    /// provided that can later be signed and sent onchain.
935
    function startBroadcast(uint256 privateKey) external;
936

                            
                        
937
    /// Stops collecting onchain transactions.
938
    function stopBroadcast() external;
939

                            
                        
940
    // ======== String ========
941

                            
                        
942
    /// Returns the index of the first occurrence of a `key` in an `input` string.
943
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found.
944
    /// Returns 0 in case of an empty `key`.
945
    function indexOf(string calldata input, string calldata key) external pure returns (uint256);
946

                            
                        
947
    /// Parses the given `string` into an `address`.
948
    function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);
949

                            
                        
950
    /// Parses the given `string` into a `bool`.
951
    function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);
952

                            
                        
953
    /// Parses the given `string` into `bytes`.
954
    function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);
955

                            
                        
956
    /// Parses the given `string` into a `bytes32`.
957
    function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);
958

                            
                        
959
    /// Parses the given `string` into a `int256`.
960
    function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);
961

                            
                        
962
    /// Parses the given `string` into a `uint256`.
963
    function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);
964

                            
                        
965
    /// Replaces occurrences of `from` in the given `string` with `to`.
966
    function replace(string calldata input, string calldata from, string calldata to)
967
        external
968
        pure
969
        returns (string memory output);
970

                            
                        
971
    /// Splits the given `string` into an array of strings divided by the `delimiter`.
972
    function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs);
973

                            
                        
974
    /// Converts the given `string` value to Lowercase.
975
    function toLowercase(string calldata input) external pure returns (string memory output);
976

                            
                        
977
    /// Converts the given value to a `string`.
978
    function toString(address value) external pure returns (string memory stringifiedValue);
979

                            
                        
980
    /// Converts the given value to a `string`.
981
    function toString(bytes calldata value) external pure returns (string memory stringifiedValue);
982

                            
                        
983
    /// Converts the given value to a `string`.
984
    function toString(bytes32 value) external pure returns (string memory stringifiedValue);
985

                            
                        
986
    /// Converts the given value to a `string`.
987
    function toString(bool value) external pure returns (string memory stringifiedValue);
988

                            
                        
989
    /// Converts the given value to a `string`.
990
    function toString(uint256 value) external pure returns (string memory stringifiedValue);
991

                            
                        
992
    /// Converts the given value to a `string`.
993
    function toString(int256 value) external pure returns (string memory stringifiedValue);
994

                            
                        
995
    /// Converts the given `string` value to Uppercase.
996
    function toUppercase(string calldata input) external pure returns (string memory output);
997

                            
                        
998
    /// Trims leading and trailing whitespace from the given `string` value.
999
    function trim(string calldata input) external pure returns (string memory output);
1000

                            
                        
1001
    // ======== Testing ========
1002

                            
                        
1003
    /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
1004
    /// Formats values with decimals in failure message.
1005
    function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure;
1006

                            
                        
1007
    /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
1008
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1009
    function assertApproxEqAbsDecimal(
1010
        uint256 left,
1011
        uint256 right,
1012
        uint256 maxDelta,
1013
        uint256 decimals,
1014
        string calldata error
1015
    ) external pure;
1016

                            
                        
1017
    /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
1018
    /// Formats values with decimals in failure message.
1019
    function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure;
1020

                            
                        
1021
    /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
1022
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1023
    function assertApproxEqAbsDecimal(
1024
        int256 left,
1025
        int256 right,
1026
        uint256 maxDelta,
1027
        uint256 decimals,
1028
        string calldata error
1029
    ) external pure;
1030

                            
                        
1031
    /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
1032
    function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure;
1033

                            
                        
1034
    /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
1035
    /// Includes error message into revert string on failure.
1036
    function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure;
1037

                            
                        
1038
    /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
1039
    function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure;
1040

                            
                        
1041
    /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
1042
    /// Includes error message into revert string on failure.
1043
    function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure;
1044

                            
                        
1045
    /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1046
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1047
    /// Formats values with decimals in failure message.
1048
    function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals)
1049
        external
1050
        pure;
1051

                            
                        
1052
    /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1053
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1054
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1055
    function assertApproxEqRelDecimal(
1056
        uint256 left,
1057
        uint256 right,
1058
        uint256 maxPercentDelta,
1059
        uint256 decimals,
1060
        string calldata error
1061
    ) external pure;
1062

                            
                        
1063
    /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1064
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1065
    /// Formats values with decimals in failure message.
1066
    function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals)
1067
        external
1068
        pure;
1069

                            
                        
1070
    /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1071
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1072
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1073
    function assertApproxEqRelDecimal(
1074
        int256 left,
1075
        int256 right,
1076
        uint256 maxPercentDelta,
1077
        uint256 decimals,
1078
        string calldata error
1079
    ) external pure;
1080

                            
                        
1081
    /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1082
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1083
    function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure;
1084

                            
                        
1085
    /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1086
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1087
    /// Includes error message into revert string on failure.
1088
    function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error)
1089
        external
1090
        pure;
1091

                            
                        
1092
    /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1093
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1094
    function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure;
1095

                            
                        
1096
    /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
1097
    /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
1098
    /// Includes error message into revert string on failure.
1099
    function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error)
1100
        external
1101
        pure;
1102

                            
                        
1103
    /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
1104
    function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1105

                            
                        
1106
    /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
1107
    /// Includes error message into revert string on failure.
1108
    function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1109

                            
                        
1110
    /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
1111
    function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure;
1112

                            
                        
1113
    /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
1114
    /// Includes error message into revert string on failure.
1115
    function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1116

                            
                        
1117
    /// Asserts that two `bool` values are equal.
1118
    function assertEq(bool left, bool right) external pure;
1119

                            
                        
1120
    /// Asserts that two `bool` values are equal and includes error message into revert string on failure.
1121
    function assertEq(bool left, bool right, string calldata error) external pure;
1122

                            
                        
1123
    /// Asserts that two `string` values are equal.
1124
    function assertEq(string calldata left, string calldata right) external pure;
1125

                            
                        
1126
    /// Asserts that two `string` values are equal and includes error message into revert string on failure.
1127
    function assertEq(string calldata left, string calldata right, string calldata error) external pure;
1128

                            
                        
1129
    /// Asserts that two `bytes` values are equal.
1130
    function assertEq(bytes calldata left, bytes calldata right) external pure;
1131

                            
                        
1132
    /// Asserts that two `bytes` values are equal and includes error message into revert string on failure.
1133
    function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure;
1134

                            
                        
1135
    /// Asserts that two arrays of `bool` values are equal.
1136
    function assertEq(bool[] calldata left, bool[] calldata right) external pure;
1137

                            
                        
1138
    /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure.
1139
    function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;
1140

                            
                        
1141
    /// Asserts that two arrays of `uint256 values are equal.
1142
    function assertEq(uint256[] calldata left, uint256[] calldata right) external pure;
1143

                            
                        
1144
    /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure.
1145
    function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;
1146

                            
                        
1147
    /// Asserts that two arrays of `int256` values are equal.
1148
    function assertEq(int256[] calldata left, int256[] calldata right) external pure;
1149

                            
                        
1150
    /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure.
1151
    function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;
1152

                            
                        
1153
    /// Asserts that two `uint256` values are equal.
1154
    function assertEq(uint256 left, uint256 right) external pure;
1155

                            
                        
1156
    /// Asserts that two arrays of `address` values are equal.
1157
    function assertEq(address[] calldata left, address[] calldata right) external pure;
1158

                            
                        
1159
    /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure.
1160
    function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure;
1161

                            
                        
1162
    /// Asserts that two arrays of `bytes32` values are equal.
1163
    function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure;
1164

                            
                        
1165
    /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure.
1166
    function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;
1167

                            
                        
1168
    /// Asserts that two arrays of `string` values are equal.
1169
    function assertEq(string[] calldata left, string[] calldata right) external pure;
1170

                            
                        
1171
    /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure.
1172
    function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure;
1173

                            
                        
1174
    /// Asserts that two arrays of `bytes` values are equal.
1175
    function assertEq(bytes[] calldata left, bytes[] calldata right) external pure;
1176

                            
                        
1177
    /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure.
1178
    function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;
1179

                            
                        
1180
    /// Asserts that two `uint256` values are equal and includes error message into revert string on failure.
1181
    function assertEq(uint256 left, uint256 right, string calldata error) external pure;
1182

                            
                        
1183
    /// Asserts that two `int256` values are equal.
1184
    function assertEq(int256 left, int256 right) external pure;
1185

                            
                        
1186
    /// Asserts that two `int256` values are equal and includes error message into revert string on failure.
1187
    function assertEq(int256 left, int256 right, string calldata error) external pure;
1188

                            
                        
1189
    /// Asserts that two `address` values are equal.
1190
    function assertEq(address left, address right) external pure;
1191

                            
                        
1192
    /// Asserts that two `address` values are equal and includes error message into revert string on failure.
1193
    function assertEq(address left, address right, string calldata error) external pure;
1194

                            
                        
1195
    /// Asserts that two `bytes32` values are equal.
1196
    function assertEq(bytes32 left, bytes32 right) external pure;
1197

                            
                        
1198
    /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure.
1199
    function assertEq(bytes32 left, bytes32 right, string calldata error) external pure;
1200

                            
                        
1201
    /// Asserts that the given condition is false.
1202
    function assertFalse(bool condition) external pure;
1203

                            
                        
1204
    /// Asserts that the given condition is false and includes error message into revert string on failure.
1205
    function assertFalse(bool condition, string calldata error) external pure;
1206

                            
                        
1207
    /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
1208
    /// Formats values with decimals in failure message.
1209
    function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1210

                            
                        
1211
    /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
1212
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1213
    function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1214

                            
                        
1215
    /// Compares two `int256` values. Expects first value to be greater than or equal to second.
1216
    /// Formats values with decimals in failure message.
1217
    function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure;
1218

                            
                        
1219
    /// Compares two `int256` values. Expects first value to be greater than or equal to second.
1220
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1221
    function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1222

                            
                        
1223
    /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
1224
    function assertGe(uint256 left, uint256 right) external pure;
1225

                            
                        
1226
    /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
1227
    /// Includes error message into revert string on failure.
1228
    function assertGe(uint256 left, uint256 right, string calldata error) external pure;
1229

                            
                        
1230
    /// Compares two `int256` values. Expects first value to be greater than or equal to second.
1231
    function assertGe(int256 left, int256 right) external pure;
1232

                            
                        
1233
    /// Compares two `int256` values. Expects first value to be greater than or equal to second.
1234
    /// Includes error message into revert string on failure.
1235
    function assertGe(int256 left, int256 right, string calldata error) external pure;
1236

                            
                        
1237
    /// Compares two `uint256` values. Expects first value to be greater than second.
1238
    /// Formats values with decimals in failure message.
1239
    function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1240

                            
                        
1241
    /// Compares two `uint256` values. Expects first value to be greater than second.
1242
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1243
    function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1244

                            
                        
1245
    /// Compares two `int256` values. Expects first value to be greater than second.
1246
    /// Formats values with decimals in failure message.
1247
    function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure;
1248

                            
                        
1249
    /// Compares two `int256` values. Expects first value to be greater than second.
1250
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1251
    function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1252

                            
                        
1253
    /// Compares two `uint256` values. Expects first value to be greater than second.
1254
    function assertGt(uint256 left, uint256 right) external pure;
1255

                            
                        
1256
    /// Compares two `uint256` values. Expects first value to be greater than second.
1257
    /// Includes error message into revert string on failure.
1258
    function assertGt(uint256 left, uint256 right, string calldata error) external pure;
1259

                            
                        
1260
    /// Compares two `int256` values. Expects first value to be greater than second.
1261
    function assertGt(int256 left, int256 right) external pure;
1262

                            
                        
1263
    /// Compares two `int256` values. Expects first value to be greater than second.
1264
    /// Includes error message into revert string on failure.
1265
    function assertGt(int256 left, int256 right, string calldata error) external pure;
1266

                            
                        
1267
    /// Compares two `uint256` values. Expects first value to be less than or equal to second.
1268
    /// Formats values with decimals in failure message.
1269
    function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1270

                            
                        
1271
    /// Compares two `uint256` values. Expects first value to be less than or equal to second.
1272
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1273
    function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1274

                            
                        
1275
    /// Compares two `int256` values. Expects first value to be less than or equal to second.
1276
    /// Formats values with decimals in failure message.
1277
    function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure;
1278

                            
                        
1279
    /// Compares two `int256` values. Expects first value to be less than or equal to second.
1280
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1281
    function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1282

                            
                        
1283
    /// Compares two `uint256` values. Expects first value to be less than or equal to second.
1284
    function assertLe(uint256 left, uint256 right) external pure;
1285

                            
                        
1286
    /// Compares two `uint256` values. Expects first value to be less than or equal to second.
1287
    /// Includes error message into revert string on failure.
1288
    function assertLe(uint256 left, uint256 right, string calldata error) external pure;
1289

                            
                        
1290
    /// Compares two `int256` values. Expects first value to be less than or equal to second.
1291
    function assertLe(int256 left, int256 right) external pure;
1292

                            
                        
1293
    /// Compares two `int256` values. Expects first value to be less than or equal to second.
1294
    /// Includes error message into revert string on failure.
1295
    function assertLe(int256 left, int256 right, string calldata error) external pure;
1296

                            
                        
1297
    /// Compares two `uint256` values. Expects first value to be less than second.
1298
    /// Formats values with decimals in failure message.
1299
    function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1300

                            
                        
1301
    /// Compares two `uint256` values. Expects first value to be less than second.
1302
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1303
    function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1304

                            
                        
1305
    /// Compares two `int256` values. Expects first value to be less than second.
1306
    /// Formats values with decimals in failure message.
1307
    function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure;
1308

                            
                        
1309
    /// Compares two `int256` values. Expects first value to be less than second.
1310
    /// Formats values with decimals in failure message. Includes error message into revert string on failure.
1311
    function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1312

                            
                        
1313
    /// Compares two `uint256` values. Expects first value to be less than second.
1314
    function assertLt(uint256 left, uint256 right) external pure;
1315

                            
                        
1316
    /// Compares two `uint256` values. Expects first value to be less than second.
1317
    /// Includes error message into revert string on failure.
1318
    function assertLt(uint256 left, uint256 right, string calldata error) external pure;
1319

                            
                        
1320
    /// Compares two `int256` values. Expects first value to be less than second.
1321
    function assertLt(int256 left, int256 right) external pure;
1322

                            
                        
1323
    /// Compares two `int256` values. Expects first value to be less than second.
1324
    /// Includes error message into revert string on failure.
1325
    function assertLt(int256 left, int256 right, string calldata error) external pure;
1326

                            
                        
1327
    /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
1328
    function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
1329

                            
                        
1330
    /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
1331
    /// Includes error message into revert string on failure.
1332
    function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
1333

                            
                        
1334
    /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
1335
    function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure;
1336

                            
                        
1337
    /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
1338
    /// Includes error message into revert string on failure.
1339
    function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
1340

                            
                        
1341
    /// Asserts that two `bool` values are not equal.
1342
    function assertNotEq(bool left, bool right) external pure;
1343

                            
                        
1344
    /// Asserts that two `bool` values are not equal and includes error message into revert string on failure.
1345
    function assertNotEq(bool left, bool right, string calldata error) external pure;
1346

                            
                        
1347
    /// Asserts that two `string` values are not equal.
1348
    function assertNotEq(string calldata left, string calldata right) external pure;
1349

                            
                        
1350
    /// Asserts that two `string` values are not equal and includes error message into revert string on failure.
1351
    function assertNotEq(string calldata left, string calldata right, string calldata error) external pure;
1352

                            
                        
1353
    /// Asserts that two `bytes` values are not equal.
1354
    function assertNotEq(bytes calldata left, bytes calldata right) external pure;
1355

                            
                        
1356
    /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure.
1357
    function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure;
1358

                            
                        
1359
    /// Asserts that two arrays of `bool` values are not equal.
1360
    function assertNotEq(bool[] calldata left, bool[] calldata right) external pure;
1361

                            
                        
1362
    /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure.
1363
    function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;
1364

                            
                        
1365
    /// Asserts that two arrays of `uint256` values are not equal.
1366
    function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure;
1367

                            
                        
1368
    /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure.
1369
    function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;
1370

                            
                        
1371
    /// Asserts that two arrays of `int256` values are not equal.
1372
    function assertNotEq(int256[] calldata left, int256[] calldata right) external pure;
1373

                            
                        
1374
    /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure.
1375
    function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;
1376

                            
                        
1377
    /// Asserts that two `uint256` values are not equal.
1378
    function assertNotEq(uint256 left, uint256 right) external pure;
1379

                            
                        
1380
    /// Asserts that two arrays of `address` values are not equal.
1381
    function assertNotEq(address[] calldata left, address[] calldata right) external pure;
1382

                            
                        
1383
    /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure.
1384
    function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure;
1385

                            
                        
1386
    /// Asserts that two arrays of `bytes32` values are not equal.
1387
    function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure;
1388

                            
                        
1389
    /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure.
1390
    function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;
1391

                            
                        
1392
    /// Asserts that two arrays of `string` values are not equal.
1393
    function assertNotEq(string[] calldata left, string[] calldata right) external pure;
1394

                            
                        
1395
    /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure.
1396
    function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure;
1397

                            
                        
1398
    /// Asserts that two arrays of `bytes` values are not equal.
1399
    function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure;
1400

                            
                        
1401
    /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure.
1402
    function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;
1403

                            
                        
1404
    /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure.
1405
    function assertNotEq(uint256 left, uint256 right, string calldata error) external pure;
1406

                            
                        
1407
    /// Asserts that two `int256` values are not equal.
1408
    function assertNotEq(int256 left, int256 right) external pure;
1409

                            
                        
1410
    /// Asserts that two `int256` values are not equal and includes error message into revert string on failure.
1411
    function assertNotEq(int256 left, int256 right, string calldata error) external pure;
1412

                            
                        
1413
    /// Asserts that two `address` values are not equal.
1414
    function assertNotEq(address left, address right) external pure;
1415

                            
                        
1416
    /// Asserts that two `address` values are not equal and includes error message into revert string on failure.
1417
    function assertNotEq(address left, address right, string calldata error) external pure;
1418

                            
                        
1419
    /// Asserts that two `bytes32` values are not equal.
1420
    function assertNotEq(bytes32 left, bytes32 right) external pure;
1421

                            
                        
1422
    /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure.
1423
    function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure;
1424

                            
                        
1425
    /// Asserts that the given condition is true.
1426
    function assertTrue(bool condition) external pure;
1427

                            
                        
1428
    /// Asserts that the given condition is true and includes error message into revert string on failure.
1429
    function assertTrue(bool condition, string calldata error) external pure;
1430

                            
                        
1431
    /// If the condition is false, discard this run's fuzz inputs and generate new ones.
1432
    function assume(bool condition) external pure;
1433

                            
                        
1434
    /// Writes a breakpoint to jump to in the debugger.
1435
    function breakpoint(string calldata char) external;
1436

                            
                        
1437
    /// Writes a conditional breakpoint to jump to in the debugger.
1438
    function breakpoint(string calldata char, bool value) external;
1439

                            
                        
1440
    /// Returns the Foundry version.
1441
    /// Format: <cargo_version>+<git_sha>+<build_timestamp>
1442
    /// Sample output: 0.2.0+faa94c384+202407110019
1443
    /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs.
1444
    /// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000)
1445
    /// to compare timestamps while ignoring minor time differences.
1446
    function getFoundryVersion() external view returns (string memory version);
1447

                            
                        
1448
    /// Returns the RPC url for the given alias.
1449
    function rpcUrl(string calldata rpcAlias) external view returns (string memory json);
1450

                            
                        
1451
    /// Returns all rpc urls and their aliases as structs.
1452
    function rpcUrlStructs() external view returns (Rpc[] memory urls);
1453

                            
                        
1454
    /// Returns all rpc urls and their aliases `[alias, url][]`.
1455
    function rpcUrls() external view returns (string[2][] memory urls);
1456

                            
                        
1457
    /// Suspends execution of the main thread for `duration` milliseconds.
1458
    function sleep(uint256 duration) external;
1459

                            
                        
1460
    // ======== Toml ========
1461

                            
                        
1462
    /// Checks if `key` exists in a TOML table.
1463
    function keyExistsToml(string calldata toml, string calldata key) external view returns (bool);
1464

                            
                        
1465
    /// Parses a string of TOML data at `key` and coerces it to `address`.
1466
    function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address);
1467

                            
                        
1468
    /// Parses a string of TOML data at `key` and coerces it to `address[]`.
1469
    function parseTomlAddressArray(string calldata toml, string calldata key)
1470
        external
1471
        pure
1472
        returns (address[] memory);
1473

                            
                        
1474
    /// Parses a string of TOML data at `key` and coerces it to `bool`.
1475
    function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool);
1476

                            
                        
1477
    /// Parses a string of TOML data at `key` and coerces it to `bool[]`.
1478
    function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory);
1479

                            
                        
1480
    /// Parses a string of TOML data at `key` and coerces it to `bytes`.
1481
    function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory);
1482

                            
                        
1483
    /// Parses a string of TOML data at `key` and coerces it to `bytes32`.
1484
    function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32);
1485

                            
                        
1486
    /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`.
1487
    function parseTomlBytes32Array(string calldata toml, string calldata key)
1488
        external
1489
        pure
1490
        returns (bytes32[] memory);
1491

                            
                        
1492
    /// Parses a string of TOML data at `key` and coerces it to `bytes[]`.
1493
    function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory);
1494

                            
                        
1495
    /// Parses a string of TOML data at `key` and coerces it to `int256`.
1496
    function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256);
1497

                            
                        
1498
    /// Parses a string of TOML data at `key` and coerces it to `int256[]`.
1499
    function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory);
1500

                            
                        
1501
    /// Returns an array of all the keys in a TOML table.
1502
    function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys);
1503

                            
                        
1504
    /// Parses a string of TOML data at `key` and coerces it to `string`.
1505
    function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory);
1506

                            
                        
1507
    /// Parses a string of TOML data at `key` and coerces it to `string[]`.
1508
    function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory);
1509

                            
                        
1510
    /// Parses a string of TOML data at `key` and coerces it to `uint256`.
1511
    function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256);
1512

                            
                        
1513
    /// Parses a string of TOML data at `key` and coerces it to `uint256[]`.
1514
    function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory);
1515

                            
                        
1516
    /// ABI-encodes a TOML table.
1517
    function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData);
1518

                            
                        
1519
    /// ABI-encodes a TOML table at `key`.
1520
    function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData);
1521

                            
                        
1522
    /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file.
1523
    function writeToml(string calldata json, string calldata path) external;
1524

                            
                        
1525
    /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = <value_key.>
1526
    /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing.
1527
    function writeToml(string calldata json, string calldata path, string calldata valueKey) external;
1528

                            
                        
1529
    // ======== Utilities ========
1530

                            
                        
1531
    /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer.
1532
    function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer)
1533
        external
1534
        pure
1535
        returns (address);
1536

                            
                        
1537
    /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer.
1538
    function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address);
1539

                            
                        
1540
    /// Compute the address a contract will be deployed at for a given deployer address and nonce.
1541
    function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address);
1542

                            
                        
1543
    /// Returns ENS namehash for provided string.
1544
    function ensNamehash(string calldata name) external pure returns (bytes32);
1545

                            
                        
1546
    /// Gets the label for the specified address.
1547
    function getLabel(address account) external view returns (string memory currentLabel);
1548

                            
                        
1549
    /// Labels an address in call traces.
1550
    function label(address account, string calldata newLabel) external;
1551

                            
                        
1552
    /// Returns a random `address`.
1553
    function randomAddress() external returns (address);
1554

                            
                        
1555
    /// Returns a random uint256 value.
1556
    function randomUint() external returns (uint256);
1557

                            
                        
1558
    /// Returns random uin256 value between the provided range (=min..=max).
1559
    function randomUint(uint256 min, uint256 max) external returns (uint256);
1560

                            
                        
1561
    /// Encodes a `bytes` value to a base64url string.
1562
    function toBase64URL(bytes calldata data) external pure returns (string memory);
1563

                            
                        
1564
    /// Encodes a `string` value to a base64url string.
1565
    function toBase64URL(string calldata data) external pure returns (string memory);
1566

                            
                        
1567
    /// Encodes a `bytes` value to a base64 string.
1568
    function toBase64(bytes calldata data) external pure returns (string memory);
1569

                            
                        
1570
    /// Encodes a `string` value to a base64 string.
1571
    function toBase64(string calldata data) external pure returns (string memory);
1572
}
1573

                            
                        
1574
/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
1575
/// in tests, but it is not recommended to use these cheats in scripts.
1576
interface Vm is VmSafe {
1577
    // ======== EVM ========
1578

                            
                        
1579
    /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.
1580
    function activeFork() external view returns (uint256 forkId);
1581

                            
                        
1582
    /// In forking mode, explicitly grant the given address cheatcode access.
1583
    function allowCheatcodes(address account) external;
1584

                            
                        
1585
    /// Sets `block.blobbasefee`
1586
    function blobBaseFee(uint256 newBlobBaseFee) external;
1587

                            
                        
1588
    /// Sets the blobhashes in the transaction.
1589
    /// Not available on EVM versions before Cancun.
1590
    /// If used on unsupported EVM versions it will revert.
1591
    function blobhashes(bytes32[] calldata hashes) external;
1592

                            
                        
1593
    /// Sets `block.chainid`.
1594
    function chainId(uint256 newChainId) external;
1595

                            
                        
1596
    /// Clears all mocked calls.
1597
    function clearMockedCalls() external;
1598

                            
                        
1599
    /// Sets `block.coinbase`.
1600
    function coinbase(address newCoinbase) external;
1601

                            
                        
1602
    /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork.
1603
    function createFork(string calldata urlOrAlias) external returns (uint256 forkId);
1604

                            
                        
1605
    /// Creates a new fork with the given endpoint and block and returns the identifier of the fork.
1606
    function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
1607

                            
                        
1608
    /// Creates a new fork with the given endpoint and at the block the given transaction was mined in,
1609
    /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork.
1610
    function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
1611

                            
                        
1612
    /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork.
1613
    function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);
1614

                            
                        
1615
    /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork.
1616
    function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
1617

                            
                        
1618
    /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in,
1619
    /// replays all transaction mined in the block before the transaction, returns the identifier of the fork.
1620
    function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
1621

                            
                        
1622
    /// Sets an address' balance.
1623
    function deal(address account, uint256 newBalance) external;
1624

                            
                        
1625
    /// Removes the snapshot with the given ID created by `snapshot`.
1626
    /// Takes the snapshot ID to delete.
1627
    /// Returns `true` if the snapshot was successfully deleted.
1628
    /// Returns `false` if the snapshot does not exist.
1629
    function deleteSnapshot(uint256 snapshotId) external returns (bool success);
1630

                            
                        
1631
    /// Removes _all_ snapshots previously created by `snapshot`.
1632
    function deleteSnapshots() external;
1633

                            
                        
1634
    /// Sets `block.difficulty`.
1635
    /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead.
1636
    /// Reverts if used on unsupported EVM versions.
1637
    function difficulty(uint256 newDifficulty) external;
1638

                            
                        
1639
    /// Dump a genesis JSON file's `allocs` to disk.
1640
    function dumpState(string calldata pathToStateJson) external;
1641

                            
                        
1642
    /// Sets an address' code.
1643
    function etch(address target, bytes calldata newRuntimeBytecode) external;
1644

                            
                        
1645
    /// Sets `block.basefee`.
1646
    function fee(uint256 newBasefee) external;
1647

                            
                        
1648
    /// Gets the blockhashes from the current transaction.
1649
    /// Not available on EVM versions before Cancun.
1650
    /// If used on unsupported EVM versions it will revert.
1651
    function getBlobhashes() external view returns (bytes32[] memory hashes);
1652

                            
                        
1653
    /// Returns true if the account is marked as persistent.
1654
    function isPersistent(address account) external view returns (bool persistent);
1655

                            
                        
1656
    /// Load a genesis JSON file's `allocs` into the in-memory revm state.
1657
    function loadAllocs(string calldata pathToAllocsJson) external;
1658

                            
                        
1659
    /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup
1660
    /// Meaning, changes made to the state of this account will be kept when switching forks.
1661
    function makePersistent(address account) external;
1662

                            
                        
1663
    /// See `makePersistent(address)`.
1664
    function makePersistent(address account0, address account1) external;
1665

                            
                        
1666
    /// See `makePersistent(address)`.
1667
    function makePersistent(address account0, address account1, address account2) external;
1668

                            
                        
1669
    /// See `makePersistent(address)`.
1670
    function makePersistent(address[] calldata accounts) external;
1671

                            
                        
1672
    /// Reverts a call to an address with specified revert data.
1673
    function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external;
1674

                            
                        
1675
    /// Reverts a call to an address with a specific `msg.value`, with specified revert data.
1676
    function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData)
1677
        external;
1678

                            
                        
1679
    /// Mocks a call to an address, returning specified data.
1680
    /// Calldata can either be strict or a partial match, e.g. if you only
1681
    /// pass a Solidity selector to the expected calldata, then the entire Solidity
1682
    /// function will be mocked.
1683
    function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;
1684

                            
                        
1685
    /// Mocks a call to an address with a specific `msg.value`, returning specified data.
1686
    /// Calldata match takes precedence over `msg.value` in case of ambiguity.
1687
    function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;
1688

                            
                        
1689
    /// Sets the *next* call's `msg.sender` to be the input address.
1690
    function prank(address msgSender) external;
1691

                            
                        
1692
    /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input.
1693
    function prank(address msgSender, address txOrigin) external;
1694

                            
                        
1695
    /// Sets `block.prevrandao`.
1696
    /// Not available on EVM versions before Paris. Use `difficulty` instead.
1697
    /// If used on unsupported EVM versions it will revert.
1698
    function prevrandao(bytes32 newPrevrandao) external;
1699

                            
                        
1700
    /// Sets `block.prevrandao`.
1701
    /// Not available on EVM versions before Paris. Use `difficulty` instead.
1702
    /// If used on unsupported EVM versions it will revert.
1703
    function prevrandao(uint256 newPrevrandao) external;
1704

                            
                        
1705
    /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification.
1706
    function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin);
1707

                            
                        
1708
    /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts.
1709
    function resetNonce(address account) external;
1710

                            
                        
1711
    /// Revert the state of the EVM to a previous snapshot
1712
    /// Takes the snapshot ID to revert to.
1713
    /// Returns `true` if the snapshot was successfully reverted.
1714
    /// Returns `false` if the snapshot does not exist.
1715
    /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`.
1716
    function revertTo(uint256 snapshotId) external returns (bool success);
1717

                            
                        
1718
    /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots
1719
    /// Takes the snapshot ID to revert to.
1720
    /// Returns `true` if the snapshot was successfully reverted and deleted.
1721
    /// Returns `false` if the snapshot does not exist.
1722
    function revertToAndDelete(uint256 snapshotId) external returns (bool success);
1723

                            
                        
1724
    /// Revokes persistent status from the address, previously added via `makePersistent`.
1725
    function revokePersistent(address account) external;
1726

                            
                        
1727
    /// See `revokePersistent(address)`.
1728
    function revokePersistent(address[] calldata accounts) external;
1729

                            
                        
1730
    /// Sets `block.height`.
1731
    function roll(uint256 newHeight) external;
1732

                            
                        
1733
    /// Updates the currently active fork to given block number
1734
    /// This is similar to `roll` but for the currently active fork.
1735
    function rollFork(uint256 blockNumber) external;
1736

                            
                        
1737
    /// Updates the currently active fork to given transaction. This will `rollFork` with the number
1738
    /// of the block the transaction was mined in and replays all transaction mined before it in the block.
1739
    function rollFork(bytes32 txHash) external;
1740

                            
                        
1741
    /// Updates the given fork to given block number.
1742
    function rollFork(uint256 forkId, uint256 blockNumber) external;
1743

                            
                        
1744
    /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block.
1745
    function rollFork(uint256 forkId, bytes32 txHash) external;
1746

                            
                        
1747
    /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
1748
    function selectFork(uint256 forkId) external;
1749

                            
                        
1750
    /// Set blockhash for the current block.
1751
    /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`.
1752
    function setBlockhash(uint256 blockNumber, bytes32 blockHash) external;
1753

                            
                        
1754
    /// Sets the nonce of an account. Must be higher than the current nonce of the account.
1755
    function setNonce(address account, uint64 newNonce) external;
1756

                            
                        
1757
    /// Sets the nonce of an account to an arbitrary value.
1758
    function setNonceUnsafe(address account, uint64 newNonce) external;
1759

                            
                        
1760
    /// Snapshot the current state of the evm.
1761
    /// Returns the ID of the snapshot that was created.
1762
    /// To revert a snapshot use `revertTo`.
1763
    function snapshot() external returns (uint256 snapshotId);
1764

                            
                        
1765
    /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called.
1766
    function startPrank(address msgSender) external;
1767

                            
                        
1768
    /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input.
1769
    function startPrank(address msgSender, address txOrigin) external;
1770

                            
                        
1771
    /// Resets subsequent calls' `msg.sender` to be `address(this)`.
1772
    function stopPrank() external;
1773

                            
                        
1774
    /// Stores a value to an address' storage slot.
1775
    function store(address target, bytes32 slot, bytes32 value) external;
1776

                            
                        
1777
    /// Fetches the given transaction from the active fork and executes it on the current state.
1778
    function transact(bytes32 txHash) external;
1779

                            
                        
1780
    /// Fetches the given transaction from the given fork and executes it on the current state.
1781
    function transact(uint256 forkId, bytes32 txHash) external;
1782

                            
                        
1783
    /// Sets `tx.gasprice`.
1784
    function txGasPrice(uint256 newGasPrice) external;
1785

                            
                        
1786
    /// Sets `block.timestamp`.
1787
    function warp(uint256 newTimestamp) external;
1788

                            
                        
1789
    // ======== Testing ========
1790

                            
                        
1791
    /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.
1792
    function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;
1793

                            
                        
1794
    /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.
1795
    function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count)
1796
        external;
1797

                            
                        
1798
    /// Expects a call to an address with the specified calldata.
1799
    /// Calldata can either be a strict or a partial match.
1800
    function expectCall(address callee, bytes calldata data) external;
1801

                            
                        
1802
    /// Expects given number of calls to an address with the specified calldata.
1803
    function expectCall(address callee, bytes calldata data, uint64 count) external;
1804

                            
                        
1805
    /// Expects a call to an address with the specified `msg.value` and calldata.
1806
    function expectCall(address callee, uint256 msgValue, bytes calldata data) external;
1807

                            
                        
1808
    /// Expects given number of calls to an address with the specified `msg.value` and calldata.
1809
    function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external;
1810

                            
                        
1811
    /// Expect a call to an address with the specified `msg.value`, gas, and calldata.
1812
    function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;
1813

                            
                        
1814
    /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata.
1815
    function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external;
1816

                            
                        
1817
    /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.).
1818
    /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if
1819
    /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
1820
    function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData)
1821
        external;
1822

                            
                        
1823
    /// Same as the previous method, but also checks supplied address against emitting contract.
1824
    function expectEmitAnonymous(
1825
        bool checkTopic0,
1826
        bool checkTopic1,
1827
        bool checkTopic2,
1828
        bool checkTopic3,
1829
        bool checkData,
1830
        address emitter
1831
    ) external;
1832

                            
                        
1833
    /// Prepare an expected anonymous log with all topic and data checks enabled.
1834
    /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if
1835
    /// logs were emitted in the expected order with the expected topics and data.
1836
    function expectEmitAnonymous() external;
1837

                            
                        
1838
    /// Same as the previous method, but also checks supplied address against emitting contract.
1839
    function expectEmitAnonymous(address emitter) external;
1840

                            
                        
1841
    /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.).
1842
    /// Call this function, then emit an event, then call a function. Internally after the call, we check if
1843
    /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
1844
    function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;
1845

                            
                        
1846
    /// Same as the previous method, but also checks supplied address against emitting contract.
1847
    function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)
1848
        external;
1849

                            
                        
1850
    /// Prepare an expected log with all topic and data checks enabled.
1851
    /// Call this function, then emit an event, then call a function. Internally after the call, we check if
1852
    /// logs were emitted in the expected order with the expected topics and data.
1853
    function expectEmit() external;
1854

                            
                        
1855
    /// Same as the previous method, but also checks supplied address against emitting contract.
1856
    function expectEmit(address emitter) external;
1857

                            
                        
1858
    /// Expects an error on next call with any revert data.
1859
    function expectRevert() external;
1860

                            
                        
1861
    /// Expects an error on next call that starts with the revert data.
1862
    function expectRevert(bytes4 revertData) external;
1863

                            
                        
1864
    /// Expects an error on next call that exactly matches the revert data.
1865
    function expectRevert(bytes calldata revertData) external;
1866

                            
                        
1867
    /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other
1868
    /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.
1869
    function expectSafeMemory(uint64 min, uint64 max) external;
1870

                            
                        
1871
    /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.
1872
    /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges
1873
    /// to the set.
1874
    function expectSafeMemoryCall(uint64 min, uint64 max) external;
1875

                            
                        
1876
    /// Marks a test as skipped. Must be called at the top of the test.
1877
    function skip(bool skipTest) external;
1878

                            
                        
1879
    /// Stops all safe memory expectation in the current subcontext.
1880
    function stopExpectSafeMemory() external;
1881
}
1882

                            
                        

Lines covered: 0 / 10 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.4.22 <0.9.0;
3

                            
                        
4
library console {
5
    address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
6

                            
                        
7
    function _castLogPayloadViewToPure(
8
        function(bytes memory) internal view fnIn
9
    ) internal pure returns (function(bytes memory) internal pure fnOut) {
10
        assembly {
11
            fnOut := fnIn
12
        }
13
    }
14

                            
                        
15
    function _sendLogPayload(bytes memory payload) internal pure {
16
        _castLogPayloadViewToPure(_sendLogPayloadView)(payload);
17
    }
18

                            
                        
19
    function _sendLogPayloadView(bytes memory payload) private view {
20
        uint256 payloadLength = payload.length;
21
        address consoleAddress = CONSOLE_ADDRESS;
22
        /// @solidity memory-safe-assembly
23
        assembly {
24
            let payloadStart := add(payload, 32)
25
            let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
26
        }
27
    }
28

                            
                        
29
    function log() internal pure {
30
        _sendLogPayload(abi.encodeWithSignature("log()"));
31
    }
32

                            
                        
33
    function logInt(int p0) internal pure {
34
        _sendLogPayload(abi.encodeWithSignature("log(int)", p0));
35
    }
36

                            
                        
37
    function logUint(uint p0) internal pure {
38
        _sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
39
    }
40

                            
                        
41
    function logString(string memory p0) internal pure {
42
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
43
    }
44

                            
                        
45
    function logBool(bool p0) internal pure {
46
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
47
    }
48

                            
                        
49
    function logAddress(address p0) internal pure {
50
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
51
    }
52

                            
                        
53
    function logBytes(bytes memory p0) internal pure {
54
        _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
55
    }
56

                            
                        
57
    function logBytes1(bytes1 p0) internal pure {
58
        _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
59
    }
60

                            
                        
61
    function logBytes2(bytes2 p0) internal pure {
62
        _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
63
    }
64

                            
                        
65
    function logBytes3(bytes3 p0) internal pure {
66
        _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
67
    }
68

                            
                        
69
    function logBytes4(bytes4 p0) internal pure {
70
        _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
71
    }
72

                            
                        
73
    function logBytes5(bytes5 p0) internal pure {
74
        _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
75
    }
76

                            
                        
77
    function logBytes6(bytes6 p0) internal pure {
78
        _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
79
    }
80

                            
                        
81
    function logBytes7(bytes7 p0) internal pure {
82
        _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
83
    }
84

                            
                        
85
    function logBytes8(bytes8 p0) internal pure {
86
        _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
87
    }
88

                            
                        
89
    function logBytes9(bytes9 p0) internal pure {
90
        _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
91
    }
92

                            
                        
93
    function logBytes10(bytes10 p0) internal pure {
94
        _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
95
    }
96

                            
                        
97
    function logBytes11(bytes11 p0) internal pure {
98
        _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
99
    }
100

                            
                        
101
    function logBytes12(bytes12 p0) internal pure {
102
        _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
103
    }
104

                            
                        
105
    function logBytes13(bytes13 p0) internal pure {
106
        _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
107
    }
108

                            
                        
109
    function logBytes14(bytes14 p0) internal pure {
110
        _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
111
    }
112

                            
                        
113
    function logBytes15(bytes15 p0) internal pure {
114
        _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
115
    }
116

                            
                        
117
    function logBytes16(bytes16 p0) internal pure {
118
        _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
119
    }
120

                            
                        
121
    function logBytes17(bytes17 p0) internal pure {
122
        _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
123
    }
124

                            
                        
125
    function logBytes18(bytes18 p0) internal pure {
126
        _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
127
    }
128

                            
                        
129
    function logBytes19(bytes19 p0) internal pure {
130
        _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
131
    }
132

                            
                        
133
    function logBytes20(bytes20 p0) internal pure {
134
        _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
135
    }
136

                            
                        
137
    function logBytes21(bytes21 p0) internal pure {
138
        _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
139
    }
140

                            
                        
141
    function logBytes22(bytes22 p0) internal pure {
142
        _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
143
    }
144

                            
                        
145
    function logBytes23(bytes23 p0) internal pure {
146
        _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
147
    }
148

                            
                        
149
    function logBytes24(bytes24 p0) internal pure {
150
        _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
151
    }
152

                            
                        
153
    function logBytes25(bytes25 p0) internal pure {
154
        _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
155
    }
156

                            
                        
157
    function logBytes26(bytes26 p0) internal pure {
158
        _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
159
    }
160

                            
                        
161
    function logBytes27(bytes27 p0) internal pure {
162
        _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
163
    }
164

                            
                        
165
    function logBytes28(bytes28 p0) internal pure {
166
        _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
167
    }
168

                            
                        
169
    function logBytes29(bytes29 p0) internal pure {
170
        _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
171
    }
172

                            
                        
173
    function logBytes30(bytes30 p0) internal pure {
174
        _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
175
    }
176

                            
                        
177
    function logBytes31(bytes31 p0) internal pure {
178
        _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
179
    }
180

                            
                        
181
    function logBytes32(bytes32 p0) internal pure {
182
        _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
183
    }
184

                            
                        
185
    function log(uint p0) internal pure {
186
        _sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
187
    }
188

                            
                        
189
    function log(int p0) internal pure {
190
        _sendLogPayload(abi.encodeWithSignature("log(int)", p0));
191
    }
192

                            
                        
193
    function log(string memory p0) internal pure {
194
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
195
    }
196

                            
                        
197
    function log(bool p0) internal pure {
198
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
199
    }
200

                            
                        
201
    function log(address p0) internal pure {
202
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
203
    }
204

                            
                        
205
    function log(uint p0, uint p1) internal pure {
206
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
207
    }
208

                            
                        
209
    function log(uint p0, string memory p1) internal pure {
210
        _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
211
    }
212

                            
                        
213
    function log(uint p0, bool p1) internal pure {
214
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
215
    }
216

                            
                        
217
    function log(uint p0, address p1) internal pure {
218
        _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
219
    }
220

                            
                        
221
    function log(string memory p0, uint p1) internal pure {
222
        _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
223
    }
224

                            
                        
225
    function log(string memory p0, int p1) internal pure {
226
        _sendLogPayload(abi.encodeWithSignature("log(string,int)", p0, p1));
227
    }
228

                            
                        
229
    function log(string memory p0, string memory p1) internal pure {
230
        _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
231
    }
232

                            
                        
233
    function log(string memory p0, bool p1) internal pure {
234
        _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
235
    }
236

                            
                        
237
    function log(string memory p0, address p1) internal pure {
238
        _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
239
    }
240

                            
                        
241
    function log(bool p0, uint p1) internal pure {
242
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
243
    }
244

                            
                        
245
    function log(bool p0, string memory p1) internal pure {
246
        _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
247
    }
248

                            
                        
249
    function log(bool p0, bool p1) internal pure {
250
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
251
    }
252

                            
                        
253
    function log(bool p0, address p1) internal pure {
254
        _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
255
    }
256

                            
                        
257
    function log(address p0, uint p1) internal pure {
258
        _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
259
    }
260

                            
                        
261
    function log(address p0, string memory p1) internal pure {
262
        _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
263
    }
264

                            
                        
265
    function log(address p0, bool p1) internal pure {
266
        _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
267
    }
268

                            
                        
269
    function log(address p0, address p1) internal pure {
270
        _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
271
    }
272

                            
                        
273
    function log(uint p0, uint p1, uint p2) internal pure {
274
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
275
    }
276

                            
                        
277
    function log(uint p0, uint p1, string memory p2) internal pure {
278
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
279
    }
280

                            
                        
281
    function log(uint p0, uint p1, bool p2) internal pure {
282
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
283
    }
284

                            
                        
285
    function log(uint p0, uint p1, address p2) internal pure {
286
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
287
    }
288

                            
                        
289
    function log(uint p0, string memory p1, uint p2) internal pure {
290
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
291
    }
292

                            
                        
293
    function log(uint p0, string memory p1, string memory p2) internal pure {
294
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
295
    }
296

                            
                        
297
    function log(uint p0, string memory p1, bool p2) internal pure {
298
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
299
    }
300

                            
                        
301
    function log(uint p0, string memory p1, address p2) internal pure {
302
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
303
    }
304

                            
                        
305
    function log(uint p0, bool p1, uint p2) internal pure {
306
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
307
    }
308

                            
                        
309
    function log(uint p0, bool p1, string memory p2) internal pure {
310
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
311
    }
312

                            
                        
313
    function log(uint p0, bool p1, bool p2) internal pure {
314
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
315
    }
316

                            
                        
317
    function log(uint p0, bool p1, address p2) internal pure {
318
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
319
    }
320

                            
                        
321
    function log(uint p0, address p1, uint p2) internal pure {
322
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
323
    }
324

                            
                        
325
    function log(uint p0, address p1, string memory p2) internal pure {
326
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
327
    }
328

                            
                        
329
    function log(uint p0, address p1, bool p2) internal pure {
330
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
331
    }
332

                            
                        
333
    function log(uint p0, address p1, address p2) internal pure {
334
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
335
    }
336

                            
                        
337
    function log(string memory p0, uint p1, uint p2) internal pure {
338
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
339
    }
340

                            
                        
341
    function log(string memory p0, uint p1, string memory p2) internal pure {
342
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
343
    }
344

                            
                        
345
    function log(string memory p0, uint p1, bool p2) internal pure {
346
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
347
    }
348

                            
                        
349
    function log(string memory p0, uint p1, address p2) internal pure {
350
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
351
    }
352

                            
                        
353
    function log(string memory p0, string memory p1, uint p2) internal pure {
354
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
355
    }
356

                            
                        
357
    function log(string memory p0, string memory p1, string memory p2) internal pure {
358
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
359
    }
360

                            
                        
361
    function log(string memory p0, string memory p1, bool p2) internal pure {
362
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
363
    }
364

                            
                        
365
    function log(string memory p0, string memory p1, address p2) internal pure {
366
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
367
    }
368

                            
                        
369
    function log(string memory p0, bool p1, uint p2) internal pure {
370
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
371
    }
372

                            
                        
373
    function log(string memory p0, bool p1, string memory p2) internal pure {
374
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
375
    }
376

                            
                        
377
    function log(string memory p0, bool p1, bool p2) internal pure {
378
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
379
    }
380

                            
                        
381
    function log(string memory p0, bool p1, address p2) internal pure {
382
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
383
    }
384

                            
                        
385
    function log(string memory p0, address p1, uint p2) internal pure {
386
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
387
    }
388

                            
                        
389
    function log(string memory p0, address p1, string memory p2) internal pure {
390
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
391
    }
392

                            
                        
393
    function log(string memory p0, address p1, bool p2) internal pure {
394
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
395
    }
396

                            
                        
397
    function log(string memory p0, address p1, address p2) internal pure {
398
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
399
    }
400

                            
                        
401
    function log(bool p0, uint p1, uint p2) internal pure {
402
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
403
    }
404

                            
                        
405
    function log(bool p0, uint p1, string memory p2) internal pure {
406
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
407
    }
408

                            
                        
409
    function log(bool p0, uint p1, bool p2) internal pure {
410
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
411
    }
412

                            
                        
413
    function log(bool p0, uint p1, address p2) internal pure {
414
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
415
    }
416

                            
                        
417
    function log(bool p0, string memory p1, uint p2) internal pure {
418
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
419
    }
420

                            
                        
421
    function log(bool p0, string memory p1, string memory p2) internal pure {
422
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
423
    }
424

                            
                        
425
    function log(bool p0, string memory p1, bool p2) internal pure {
426
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
427
    }
428

                            
                        
429
    function log(bool p0, string memory p1, address p2) internal pure {
430
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
431
    }
432

                            
                        
433
    function log(bool p0, bool p1, uint p2) internal pure {
434
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
435
    }
436

                            
                        
437
    function log(bool p0, bool p1, string memory p2) internal pure {
438
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
439
    }
440

                            
                        
441
    function log(bool p0, bool p1, bool p2) internal pure {
442
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
443
    }
444

                            
                        
445
    function log(bool p0, bool p1, address p2) internal pure {
446
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
447
    }
448

                            
                        
449
    function log(bool p0, address p1, uint p2) internal pure {
450
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
451
    }
452

                            
                        
453
    function log(bool p0, address p1, string memory p2) internal pure {
454
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
455
    }
456

                            
                        
457
    function log(bool p0, address p1, bool p2) internal pure {
458
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
459
    }
460

                            
                        
461
    function log(bool p0, address p1, address p2) internal pure {
462
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
463
    }
464

                            
                        
465
    function log(address p0, uint p1, uint p2) internal pure {
466
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
467
    }
468

                            
                        
469
    function log(address p0, uint p1, string memory p2) internal pure {
470
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
471
    }
472

                            
                        
473
    function log(address p0, uint p1, bool p2) internal pure {
474
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
475
    }
476

                            
                        
477
    function log(address p0, uint p1, address p2) internal pure {
478
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
479
    }
480

                            
                        
481
    function log(address p0, string memory p1, uint p2) internal pure {
482
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
483
    }
484

                            
                        
485
    function log(address p0, string memory p1, string memory p2) internal pure {
486
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
487
    }
488

                            
                        
489
    function log(address p0, string memory p1, bool p2) internal pure {
490
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
491
    }
492

                            
                        
493
    function log(address p0, string memory p1, address p2) internal pure {
494
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
495
    }
496

                            
                        
497
    function log(address p0, bool p1, uint p2) internal pure {
498
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
499
    }
500

                            
                        
501
    function log(address p0, bool p1, string memory p2) internal pure {
502
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
503
    }
504

                            
                        
505
    function log(address p0, bool p1, bool p2) internal pure {
506
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
507
    }
508

                            
                        
509
    function log(address p0, bool p1, address p2) internal pure {
510
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
511
    }
512

                            
                        
513
    function log(address p0, address p1, uint p2) internal pure {
514
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
515
    }
516

                            
                        
517
    function log(address p0, address p1, string memory p2) internal pure {
518
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
519
    }
520

                            
                        
521
    function log(address p0, address p1, bool p2) internal pure {
522
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
523
    }
524

                            
                        
525
    function log(address p0, address p1, address p2) internal pure {
526
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
527
    }
528

                            
                        
529
    function log(uint p0, uint p1, uint p2, uint p3) internal pure {
530
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
531
    }
532

                            
                        
533
    function log(uint p0, uint p1, uint p2, string memory p3) internal pure {
534
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
535
    }
536

                            
                        
537
    function log(uint p0, uint p1, uint p2, bool p3) internal pure {
538
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
539
    }
540

                            
                        
541
    function log(uint p0, uint p1, uint p2, address p3) internal pure {
542
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
543
    }
544

                            
                        
545
    function log(uint p0, uint p1, string memory p2, uint p3) internal pure {
546
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
547
    }
548

                            
                        
549
    function log(uint p0, uint p1, string memory p2, string memory p3) internal pure {
550
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
551
    }
552

                            
                        
553
    function log(uint p0, uint p1, string memory p2, bool p3) internal pure {
554
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
555
    }
556

                            
                        
557
    function log(uint p0, uint p1, string memory p2, address p3) internal pure {
558
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
559
    }
560

                            
                        
561
    function log(uint p0, uint p1, bool p2, uint p3) internal pure {
562
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
563
    }
564

                            
                        
565
    function log(uint p0, uint p1, bool p2, string memory p3) internal pure {
566
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
567
    }
568

                            
                        
569
    function log(uint p0, uint p1, bool p2, bool p3) internal pure {
570
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
571
    }
572

                            
                        
573
    function log(uint p0, uint p1, bool p2, address p3) internal pure {
574
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
575
    }
576

                            
                        
577
    function log(uint p0, uint p1, address p2, uint p3) internal pure {
578
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
579
    }
580

                            
                        
581
    function log(uint p0, uint p1, address p2, string memory p3) internal pure {
582
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
583
    }
584

                            
                        
585
    function log(uint p0, uint p1, address p2, bool p3) internal pure {
586
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
587
    }
588

                            
                        
589
    function log(uint p0, uint p1, address p2, address p3) internal pure {
590
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
591
    }
592

                            
                        
593
    function log(uint p0, string memory p1, uint p2, uint p3) internal pure {
594
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
595
    }
596

                            
                        
597
    function log(uint p0, string memory p1, uint p2, string memory p3) internal pure {
598
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
599
    }
600

                            
                        
601
    function log(uint p0, string memory p1, uint p2, bool p3) internal pure {
602
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
603
    }
604

                            
                        
605
    function log(uint p0, string memory p1, uint p2, address p3) internal pure {
606
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
607
    }
608

                            
                        
609
    function log(uint p0, string memory p1, string memory p2, uint p3) internal pure {
610
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
611
    }
612

                            
                        
613
    function log(uint p0, string memory p1, string memory p2, string memory p3) internal pure {
614
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
615
    }
616

                            
                        
617
    function log(uint p0, string memory p1, string memory p2, bool p3) internal pure {
618
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
619
    }
620

                            
                        
621
    function log(uint p0, string memory p1, string memory p2, address p3) internal pure {
622
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
623
    }
624

                            
                        
625
    function log(uint p0, string memory p1, bool p2, uint p3) internal pure {
626
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
627
    }
628

                            
                        
629
    function log(uint p0, string memory p1, bool p2, string memory p3) internal pure {
630
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
631
    }
632

                            
                        
633
    function log(uint p0, string memory p1, bool p2, bool p3) internal pure {
634
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
635
    }
636

                            
                        
637
    function log(uint p0, string memory p1, bool p2, address p3) internal pure {
638
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
639
    }
640

                            
                        
641
    function log(uint p0, string memory p1, address p2, uint p3) internal pure {
642
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
643
    }
644

                            
                        
645
    function log(uint p0, string memory p1, address p2, string memory p3) internal pure {
646
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
647
    }
648

                            
                        
649
    function log(uint p0, string memory p1, address p2, bool p3) internal pure {
650
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
651
    }
652

                            
                        
653
    function log(uint p0, string memory p1, address p2, address p3) internal pure {
654
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
655
    }
656

                            
                        
657
    function log(uint p0, bool p1, uint p2, uint p3) internal pure {
658
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
659
    }
660

                            
                        
661
    function log(uint p0, bool p1, uint p2, string memory p3) internal pure {
662
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
663
    }
664

                            
                        
665
    function log(uint p0, bool p1, uint p2, bool p3) internal pure {
666
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
667
    }
668

                            
                        
669
    function log(uint p0, bool p1, uint p2, address p3) internal pure {
670
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
671
    }
672

                            
                        
673
    function log(uint p0, bool p1, string memory p2, uint p3) internal pure {
674
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
675
    }
676

                            
                        
677
    function log(uint p0, bool p1, string memory p2, string memory p3) internal pure {
678
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
679
    }
680

                            
                        
681
    function log(uint p0, bool p1, string memory p2, bool p3) internal pure {
682
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
683
    }
684

                            
                        
685
    function log(uint p0, bool p1, string memory p2, address p3) internal pure {
686
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
687
    }
688

                            
                        
689
    function log(uint p0, bool p1, bool p2, uint p3) internal pure {
690
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
691
    }
692

                            
                        
693
    function log(uint p0, bool p1, bool p2, string memory p3) internal pure {
694
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
695
    }
696

                            
                        
697
    function log(uint p0, bool p1, bool p2, bool p3) internal pure {
698
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
699
    }
700

                            
                        
701
    function log(uint p0, bool p1, bool p2, address p3) internal pure {
702
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
703
    }
704

                            
                        
705
    function log(uint p0, bool p1, address p2, uint p3) internal pure {
706
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
707
    }
708

                            
                        
709
    function log(uint p0, bool p1, address p2, string memory p3) internal pure {
710
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
711
    }
712

                            
                        
713
    function log(uint p0, bool p1, address p2, bool p3) internal pure {
714
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
715
    }
716

                            
                        
717
    function log(uint p0, bool p1, address p2, address p3) internal pure {
718
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
719
    }
720

                            
                        
721
    function log(uint p0, address p1, uint p2, uint p3) internal pure {
722
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
723
    }
724

                            
                        
725
    function log(uint p0, address p1, uint p2, string memory p3) internal pure {
726
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
727
    }
728

                            
                        
729
    function log(uint p0, address p1, uint p2, bool p3) internal pure {
730
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
731
    }
732

                            
                        
733
    function log(uint p0, address p1, uint p2, address p3) internal pure {
734
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
735
    }
736

                            
                        
737
    function log(uint p0, address p1, string memory p2, uint p3) internal pure {
738
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
739
    }
740

                            
                        
741
    function log(uint p0, address p1, string memory p2, string memory p3) internal pure {
742
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
743
    }
744

                            
                        
745
    function log(uint p0, address p1, string memory p2, bool p3) internal pure {
746
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
747
    }
748

                            
                        
749
    function log(uint p0, address p1, string memory p2, address p3) internal pure {
750
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
751
    }
752

                            
                        
753
    function log(uint p0, address p1, bool p2, uint p3) internal pure {
754
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
755
    }
756

                            
                        
757
    function log(uint p0, address p1, bool p2, string memory p3) internal pure {
758
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
759
    }
760

                            
                        
761
    function log(uint p0, address p1, bool p2, bool p3) internal pure {
762
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
763
    }
764

                            
                        
765
    function log(uint p0, address p1, bool p2, address p3) internal pure {
766
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
767
    }
768

                            
                        
769
    function log(uint p0, address p1, address p2, uint p3) internal pure {
770
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
771
    }
772

                            
                        
773
    function log(uint p0, address p1, address p2, string memory p3) internal pure {
774
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
775
    }
776

                            
                        
777
    function log(uint p0, address p1, address p2, bool p3) internal pure {
778
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
779
    }
780

                            
                        
781
    function log(uint p0, address p1, address p2, address p3) internal pure {
782
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
783
    }
784

                            
                        
785
    function log(string memory p0, uint p1, uint p2, uint p3) internal pure {
786
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
787
    }
788

                            
                        
789
    function log(string memory p0, uint p1, uint p2, string memory p3) internal pure {
790
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
791
    }
792

                            
                        
793
    function log(string memory p0, uint p1, uint p2, bool p3) internal pure {
794
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
795
    }
796

                            
                        
797
    function log(string memory p0, uint p1, uint p2, address p3) internal pure {
798
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
799
    }
800

                            
                        
801
    function log(string memory p0, uint p1, string memory p2, uint p3) internal pure {
802
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
803
    }
804

                            
                        
805
    function log(string memory p0, uint p1, string memory p2, string memory p3) internal pure {
806
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
807
    }
808

                            
                        
809
    function log(string memory p0, uint p1, string memory p2, bool p3) internal pure {
810
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
811
    }
812

                            
                        
813
    function log(string memory p0, uint p1, string memory p2, address p3) internal pure {
814
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
815
    }
816

                            
                        
817
    function log(string memory p0, uint p1, bool p2, uint p3) internal pure {
818
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
819
    }
820

                            
                        
821
    function log(string memory p0, uint p1, bool p2, string memory p3) internal pure {
822
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
823
    }
824

                            
                        
825
    function log(string memory p0, uint p1, bool p2, bool p3) internal pure {
826
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
827
    }
828

                            
                        
829
    function log(string memory p0, uint p1, bool p2, address p3) internal pure {
830
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
831
    }
832

                            
                        
833
    function log(string memory p0, uint p1, address p2, uint p3) internal pure {
834
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
835
    }
836

                            
                        
837
    function log(string memory p0, uint p1, address p2, string memory p3) internal pure {
838
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
839
    }
840

                            
                        
841
    function log(string memory p0, uint p1, address p2, bool p3) internal pure {
842
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
843
    }
844

                            
                        
845
    function log(string memory p0, uint p1, address p2, address p3) internal pure {
846
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
847
    }
848

                            
                        
849
    function log(string memory p0, string memory p1, uint p2, uint p3) internal pure {
850
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
851
    }
852

                            
                        
853
    function log(string memory p0, string memory p1, uint p2, string memory p3) internal pure {
854
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
855
    }
856

                            
                        
857
    function log(string memory p0, string memory p1, uint p2, bool p3) internal pure {
858
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
859
    }
860

                            
                        
861
    function log(string memory p0, string memory p1, uint p2, address p3) internal pure {
862
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
863
    }
864

                            
                        
865
    function log(string memory p0, string memory p1, string memory p2, uint p3) internal pure {
866
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
867
    }
868

                            
                        
869
    function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
870
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
871
    }
872

                            
                        
873
    function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
874
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
875
    }
876

                            
                        
877
    function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
878
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
879
    }
880

                            
                        
881
    function log(string memory p0, string memory p1, bool p2, uint p3) internal pure {
882
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
883
    }
884

                            
                        
885
    function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
886
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
887
    }
888

                            
                        
889
    function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
890
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
891
    }
892

                            
                        
893
    function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
894
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
895
    }
896

                            
                        
897
    function log(string memory p0, string memory p1, address p2, uint p3) internal pure {
898
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
899
    }
900

                            
                        
901
    function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
902
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
903
    }
904

                            
                        
905
    function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
906
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
907
    }
908

                            
                        
909
    function log(string memory p0, string memory p1, address p2, address p3) internal pure {
910
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
911
    }
912

                            
                        
913
    function log(string memory p0, bool p1, uint p2, uint p3) internal pure {
914
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
915
    }
916

                            
                        
917
    function log(string memory p0, bool p1, uint p2, string memory p3) internal pure {
918
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
919
    }
920

                            
                        
921
    function log(string memory p0, bool p1, uint p2, bool p3) internal pure {
922
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
923
    }
924

                            
                        
925
    function log(string memory p0, bool p1, uint p2, address p3) internal pure {
926
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
927
    }
928

                            
                        
929
    function log(string memory p0, bool p1, string memory p2, uint p3) internal pure {
930
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
931
    }
932

                            
                        
933
    function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
934
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
935
    }
936

                            
                        
937
    function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
938
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
939
    }
940

                            
                        
941
    function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
942
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
943
    }
944

                            
                        
945
    function log(string memory p0, bool p1, bool p2, uint p3) internal pure {
946
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
947
    }
948

                            
                        
949
    function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
950
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
951
    }
952

                            
                        
953
    function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
954
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
955
    }
956

                            
                        
957
    function log(string memory p0, bool p1, bool p2, address p3) internal pure {
958
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
959
    }
960

                            
                        
961
    function log(string memory p0, bool p1, address p2, uint p3) internal pure {
962
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
963
    }
964

                            
                        
965
    function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
966
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
967
    }
968

                            
                        
969
    function log(string memory p0, bool p1, address p2, bool p3) internal pure {
970
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
971
    }
972

                            
                        
973
    function log(string memory p0, bool p1, address p2, address p3) internal pure {
974
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
975
    }
976

                            
                        
977
    function log(string memory p0, address p1, uint p2, uint p3) internal pure {
978
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
979
    }
980

                            
                        
981
    function log(string memory p0, address p1, uint p2, string memory p3) internal pure {
982
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
983
    }
984

                            
                        
985
    function log(string memory p0, address p1, uint p2, bool p3) internal pure {
986
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
987
    }
988

                            
                        
989
    function log(string memory p0, address p1, uint p2, address p3) internal pure {
990
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
991
    }
992

                            
                        
993
    function log(string memory p0, address p1, string memory p2, uint p3) internal pure {
994
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
995
    }
996

                            
                        
997
    function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
998
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
999
    }
1000

                            
                        
1001
    function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
1002
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
1003
    }
1004

                            
                        
1005
    function log(string memory p0, address p1, string memory p2, address p3) internal pure {
1006
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
1007
    }
1008

                            
                        
1009
    function log(string memory p0, address p1, bool p2, uint p3) internal pure {
1010
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
1011
    }
1012

                            
                        
1013
    function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
1014
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
1015
    }
1016

                            
                        
1017
    function log(string memory p0, address p1, bool p2, bool p3) internal pure {
1018
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
1019
    }
1020

                            
                        
1021
    function log(string memory p0, address p1, bool p2, address p3) internal pure {
1022
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
1023
    }
1024

                            
                        
1025
    function log(string memory p0, address p1, address p2, uint p3) internal pure {
1026
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
1027
    }
1028

                            
                        
1029
    function log(string memory p0, address p1, address p2, string memory p3) internal pure {
1030
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
1031
    }
1032

                            
                        
1033
    function log(string memory p0, address p1, address p2, bool p3) internal pure {
1034
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
1035
    }
1036

                            
                        
1037
    function log(string memory p0, address p1, address p2, address p3) internal pure {
1038
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
1039
    }
1040

                            
                        
1041
    function log(bool p0, uint p1, uint p2, uint p3) internal pure {
1042
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
1043
    }
1044

                            
                        
1045
    function log(bool p0, uint p1, uint p2, string memory p3) internal pure {
1046
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
1047
    }
1048

                            
                        
1049
    function log(bool p0, uint p1, uint p2, bool p3) internal pure {
1050
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
1051
    }
1052

                            
                        
1053
    function log(bool p0, uint p1, uint p2, address p3) internal pure {
1054
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
1055
    }
1056

                            
                        
1057
    function log(bool p0, uint p1, string memory p2, uint p3) internal pure {
1058
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
1059
    }
1060

                            
                        
1061
    function log(bool p0, uint p1, string memory p2, string memory p3) internal pure {
1062
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
1063
    }
1064

                            
                        
1065
    function log(bool p0, uint p1, string memory p2, bool p3) internal pure {
1066
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
1067
    }
1068

                            
                        
1069
    function log(bool p0, uint p1, string memory p2, address p3) internal pure {
1070
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
1071
    }
1072

                            
                        
1073
    function log(bool p0, uint p1, bool p2, uint p3) internal pure {
1074
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
1075
    }
1076

                            
                        
1077
    function log(bool p0, uint p1, bool p2, string memory p3) internal pure {
1078
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
1079
    }
1080

                            
                        
1081
    function log(bool p0, uint p1, bool p2, bool p3) internal pure {
1082
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
1083
    }
1084

                            
                        
1085
    function log(bool p0, uint p1, bool p2, address p3) internal pure {
1086
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
1087
    }
1088

                            
                        
1089
    function log(bool p0, uint p1, address p2, uint p3) internal pure {
1090
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
1091
    }
1092

                            
                        
1093
    function log(bool p0, uint p1, address p2, string memory p3) internal pure {
1094
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
1095
    }
1096

                            
                        
1097
    function log(bool p0, uint p1, address p2, bool p3) internal pure {
1098
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
1099
    }
1100

                            
                        
1101
    function log(bool p0, uint p1, address p2, address p3) internal pure {
1102
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
1103
    }
1104

                            
                        
1105
    function log(bool p0, string memory p1, uint p2, uint p3) internal pure {
1106
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
1107
    }
1108

                            
                        
1109
    function log(bool p0, string memory p1, uint p2, string memory p3) internal pure {
1110
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
1111
    }
1112

                            
                        
1113
    function log(bool p0, string memory p1, uint p2, bool p3) internal pure {
1114
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
1115
    }
1116

                            
                        
1117
    function log(bool p0, string memory p1, uint p2, address p3) internal pure {
1118
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
1119
    }
1120

                            
                        
1121
    function log(bool p0, string memory p1, string memory p2, uint p3) internal pure {
1122
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
1123
    }
1124

                            
                        
1125
    function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
1126
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
1127
    }
1128

                            
                        
1129
    function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
1130
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
1131
    }
1132

                            
                        
1133
    function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
1134
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
1135
    }
1136

                            
                        
1137
    function log(bool p0, string memory p1, bool p2, uint p3) internal pure {
1138
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
1139
    }
1140

                            
                        
1141
    function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
1142
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
1143
    }
1144

                            
                        
1145
    function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
1146
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
1147
    }
1148

                            
                        
1149
    function log(bool p0, string memory p1, bool p2, address p3) internal pure {
1150
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
1151
    }
1152

                            
                        
1153
    function log(bool p0, string memory p1, address p2, uint p3) internal pure {
1154
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
1155
    }
1156

                            
                        
1157
    function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
1158
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
1159
    }
1160

                            
                        
1161
    function log(bool p0, string memory p1, address p2, bool p3) internal pure {
1162
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
1163
    }
1164

                            
                        
1165
    function log(bool p0, string memory p1, address p2, address p3) internal pure {
1166
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
1167
    }
1168

                            
                        
1169
    function log(bool p0, bool p1, uint p2, uint p3) internal pure {
1170
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
1171
    }
1172

                            
                        
1173
    function log(bool p0, bool p1, uint p2, string memory p3) internal pure {
1174
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
1175
    }
1176

                            
                        
1177
    function log(bool p0, bool p1, uint p2, bool p3) internal pure {
1178
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
1179
    }
1180

                            
                        
1181
    function log(bool p0, bool p1, uint p2, address p3) internal pure {
1182
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
1183
    }
1184

                            
                        
1185
    function log(bool p0, bool p1, string memory p2, uint p3) internal pure {
1186
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
1187
    }
1188

                            
                        
1189
    function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
1190
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
1191
    }
1192

                            
                        
1193
    function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
1194
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
1195
    }
1196

                            
                        
1197
    function log(bool p0, bool p1, string memory p2, address p3) internal pure {
1198
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
1199
    }
1200

                            
                        
1201
    function log(bool p0, bool p1, bool p2, uint p3) internal pure {
1202
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
1203
    }
1204

                            
                        
1205
    function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
1206
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
1207
    }
1208

                            
                        
1209
    function log(bool p0, bool p1, bool p2, bool p3) internal pure {
1210
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
1211
    }
1212

                            
                        
1213
    function log(bool p0, bool p1, bool p2, address p3) internal pure {
1214
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
1215
    }
1216

                            
                        
1217
    function log(bool p0, bool p1, address p2, uint p3) internal pure {
1218
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
1219
    }
1220

                            
                        
1221
    function log(bool p0, bool p1, address p2, string memory p3) internal pure {
1222
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
1223
    }
1224

                            
                        
1225
    function log(bool p0, bool p1, address p2, bool p3) internal pure {
1226
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
1227
    }
1228

                            
                        
1229
    function log(bool p0, bool p1, address p2, address p3) internal pure {
1230
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
1231
    }
1232

                            
                        
1233
    function log(bool p0, address p1, uint p2, uint p3) internal pure {
1234
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
1235
    }
1236

                            
                        
1237
    function log(bool p0, address p1, uint p2, string memory p3) internal pure {
1238
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
1239
    }
1240

                            
                        
1241
    function log(bool p0, address p1, uint p2, bool p3) internal pure {
1242
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
1243
    }
1244

                            
                        
1245
    function log(bool p0, address p1, uint p2, address p3) internal pure {
1246
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
1247
    }
1248

                            
                        
1249
    function log(bool p0, address p1, string memory p2, uint p3) internal pure {
1250
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
1251
    }
1252

                            
                        
1253
    function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
1254
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
1255
    }
1256

                            
                        
1257
    function log(bool p0, address p1, string memory p2, bool p3) internal pure {
1258
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
1259
    }
1260

                            
                        
1261
    function log(bool p0, address p1, string memory p2, address p3) internal pure {
1262
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
1263
    }
1264

                            
                        
1265
    function log(bool p0, address p1, bool p2, uint p3) internal pure {
1266
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
1267
    }
1268

                            
                        
1269
    function log(bool p0, address p1, bool p2, string memory p3) internal pure {
1270
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
1271
    }
1272

                            
                        
1273
    function log(bool p0, address p1, bool p2, bool p3) internal pure {
1274
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
1275
    }
1276

                            
                        
1277
    function log(bool p0, address p1, bool p2, address p3) internal pure {
1278
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
1279
    }
1280

                            
                        
1281
    function log(bool p0, address p1, address p2, uint p3) internal pure {
1282
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
1283
    }
1284

                            
                        
1285
    function log(bool p0, address p1, address p2, string memory p3) internal pure {
1286
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
1287
    }
1288

                            
                        
1289
    function log(bool p0, address p1, address p2, bool p3) internal pure {
1290
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
1291
    }
1292

                            
                        
1293
    function log(bool p0, address p1, address p2, address p3) internal pure {
1294
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
1295
    }
1296

                            
                        
1297
    function log(address p0, uint p1, uint p2, uint p3) internal pure {
1298
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
1299
    }
1300

                            
                        
1301
    function log(address p0, uint p1, uint p2, string memory p3) internal pure {
1302
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
1303
    }
1304

                            
                        
1305
    function log(address p0, uint p1, uint p2, bool p3) internal pure {
1306
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
1307
    }
1308

                            
                        
1309
    function log(address p0, uint p1, uint p2, address p3) internal pure {
1310
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
1311
    }
1312

                            
                        
1313
    function log(address p0, uint p1, string memory p2, uint p3) internal pure {
1314
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
1315
    }
1316

                            
                        
1317
    function log(address p0, uint p1, string memory p2, string memory p3) internal pure {
1318
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
1319
    }
1320

                            
                        
1321
    function log(address p0, uint p1, string memory p2, bool p3) internal pure {
1322
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
1323
    }
1324

                            
                        
1325
    function log(address p0, uint p1, string memory p2, address p3) internal pure {
1326
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
1327
    }
1328

                            
                        
1329
    function log(address p0, uint p1, bool p2, uint p3) internal pure {
1330
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
1331
    }
1332

                            
                        
1333
    function log(address p0, uint p1, bool p2, string memory p3) internal pure {
1334
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
1335
    }
1336

                            
                        
1337
    function log(address p0, uint p1, bool p2, bool p3) internal pure {
1338
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
1339
    }
1340

                            
                        
1341
    function log(address p0, uint p1, bool p2, address p3) internal pure {
1342
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
1343
    }
1344

                            
                        
1345
    function log(address p0, uint p1, address p2, uint p3) internal pure {
1346
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
1347
    }
1348

                            
                        
1349
    function log(address p0, uint p1, address p2, string memory p3) internal pure {
1350
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
1351
    }
1352

                            
                        
1353
    function log(address p0, uint p1, address p2, bool p3) internal pure {
1354
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
1355
    }
1356

                            
                        
1357
    function log(address p0, uint p1, address p2, address p3) internal pure {
1358
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
1359
    }
1360

                            
                        
1361
    function log(address p0, string memory p1, uint p2, uint p3) internal pure {
1362
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
1363
    }
1364

                            
                        
1365
    function log(address p0, string memory p1, uint p2, string memory p3) internal pure {
1366
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
1367
    }
1368

                            
                        
1369
    function log(address p0, string memory p1, uint p2, bool p3) internal pure {
1370
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
1371
    }
1372

                            
                        
1373
    function log(address p0, string memory p1, uint p2, address p3) internal pure {
1374
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
1375
    }
1376

                            
                        
1377
    function log(address p0, string memory p1, string memory p2, uint p3) internal pure {
1378
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
1379
    }
1380

                            
                        
1381
    function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
1382
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
1383
    }
1384

                            
                        
1385
    function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
1386
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
1387
    }
1388

                            
                        
1389
    function log(address p0, string memory p1, string memory p2, address p3) internal pure {
1390
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
1391
    }
1392

                            
                        
1393
    function log(address p0, string memory p1, bool p2, uint p3) internal pure {
1394
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
1395
    }
1396

                            
                        
1397
    function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
1398
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
1399
    }
1400

                            
                        
1401
    function log(address p0, string memory p1, bool p2, bool p3) internal pure {
1402
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
1403
    }
1404

                            
                        
1405
    function log(address p0, string memory p1, bool p2, address p3) internal pure {
1406
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
1407
    }
1408

                            
                        
1409
    function log(address p0, string memory p1, address p2, uint p3) internal pure {
1410
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
1411
    }
1412

                            
                        
1413
    function log(address p0, string memory p1, address p2, string memory p3) internal pure {
1414
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
1415
    }
1416

                            
                        
1417
    function log(address p0, string memory p1, address p2, bool p3) internal pure {
1418
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
1419
    }
1420

                            
                        
1421
    function log(address p0, string memory p1, address p2, address p3) internal pure {
1422
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
1423
    }
1424

                            
                        
1425
    function log(address p0, bool p1, uint p2, uint p3) internal pure {
1426
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
1427
    }
1428

                            
                        
1429
    function log(address p0, bool p1, uint p2, string memory p3) internal pure {
1430
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
1431
    }
1432

                            
                        
1433
    function log(address p0, bool p1, uint p2, bool p3) internal pure {
1434
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
1435
    }
1436

                            
                        
1437
    function log(address p0, bool p1, uint p2, address p3) internal pure {
1438
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
1439
    }
1440

                            
                        
1441
    function log(address p0, bool p1, string memory p2, uint p3) internal pure {
1442
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
1443
    }
1444

                            
                        
1445
    function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
1446
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
1447
    }
1448

                            
                        
1449
    function log(address p0, bool p1, string memory p2, bool p3) internal pure {
1450
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
1451
    }
1452

                            
                        
1453
    function log(address p0, bool p1, string memory p2, address p3) internal pure {
1454
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
1455
    }
1456

                            
                        
1457
    function log(address p0, bool p1, bool p2, uint p3) internal pure {
1458
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
1459
    }
1460

                            
                        
1461
    function log(address p0, bool p1, bool p2, string memory p3) internal pure {
1462
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
1463
    }
1464

                            
                        
1465
    function log(address p0, bool p1, bool p2, bool p3) internal pure {
1466
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
1467
    }
1468

                            
                        
1469
    function log(address p0, bool p1, bool p2, address p3) internal pure {
1470
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
1471
    }
1472

                            
                        
1473
    function log(address p0, bool p1, address p2, uint p3) internal pure {
1474
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
1475
    }
1476

                            
                        
1477
    function log(address p0, bool p1, address p2, string memory p3) internal pure {
1478
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
1479
    }
1480

                            
                        
1481
    function log(address p0, bool p1, address p2, bool p3) internal pure {
1482
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
1483
    }
1484

                            
                        
1485
    function log(address p0, bool p1, address p2, address p3) internal pure {
1486
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
1487
    }
1488

                            
                        
1489
    function log(address p0, address p1, uint p2, uint p3) internal pure {
1490
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
1491
    }
1492

                            
                        
1493
    function log(address p0, address p1, uint p2, string memory p3) internal pure {
1494
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
1495
    }
1496

                            
                        
1497
    function log(address p0, address p1, uint p2, bool p3) internal pure {
1498
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
1499
    }
1500

                            
                        
1501
    function log(address p0, address p1, uint p2, address p3) internal pure {
1502
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
1503
    }
1504

                            
                        
1505
    function log(address p0, address p1, string memory p2, uint p3) internal pure {
1506
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
1507
    }
1508

                            
                        
1509
    function log(address p0, address p1, string memory p2, string memory p3) internal pure {
1510
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
1511
    }
1512

                            
                        
1513
    function log(address p0, address p1, string memory p2, bool p3) internal pure {
1514
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
1515
    }
1516

                            
                        
1517
    function log(address p0, address p1, string memory p2, address p3) internal pure {
1518
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
1519
    }
1520

                            
                        
1521
    function log(address p0, address p1, bool p2, uint p3) internal pure {
1522
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
1523
    }
1524

                            
                        
1525
    function log(address p0, address p1, bool p2, string memory p3) internal pure {
1526
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
1527
    }
1528

                            
                        
1529
    function log(address p0, address p1, bool p2, bool p3) internal pure {
1530
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
1531
    }
1532

                            
                        
1533
    function log(address p0, address p1, bool p2, address p3) internal pure {
1534
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
1535
    }
1536

                            
                        
1537
    function log(address p0, address p1, address p2, uint p3) internal pure {
1538
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
1539
    }
1540

                            
                        
1541
    function log(address p0, address p1, address p2, string memory p3) internal pure {
1542
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
1543
    }
1544

                            
                        
1545
    function log(address p0, address p1, address p2, bool p3) internal pure {
1546
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
1547
    }
1548

                            
                        
1549
    function log(address p0, address p1, address p2, address p3) internal pure {
1550
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
1551
    }
1552
}
1553

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.4.22 <0.9.0;
3

                            
                        
4
import {console as console2} from "./console.sol";
5

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2;
3

                            
                        
4
interface IERC165 {
5
    /// @notice Query if a contract implements an interface
6
    /// @param interfaceID The interface identifier, as specified in ERC-165
7
    /// @dev Interface identification is specified in ERC-165. This function
8
    /// uses less than 30,000 gas.
9
    /// @return `true` if the contract implements `interfaceID` and
10
    /// `interfaceID` is not 0xffffffff, `false` otherwise
11
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
12
}
13

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2;
3

                            
                        
4
/// @dev Interface of the ERC20 standard as defined in the EIP.
5
/// @dev This includes the optional name, symbol, and decimals metadata.
6
interface IERC20 {
7
    /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`).
8
    event Transfer(address indexed from, address indexed to, uint256 value);
9

                            
                        
10
    /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value`
11
    /// is the new allowance.
12
    event Approval(address indexed owner, address indexed spender, uint256 value);
13

                            
                        
14
    /// @notice Returns the amount of tokens in existence.
15
    function totalSupply() external view returns (uint256);
16

                            
                        
17
    /// @notice Returns the amount of tokens owned by `account`.
18
    function balanceOf(address account) external view returns (uint256);
19

                            
                        
20
    /// @notice Moves `amount` tokens from the caller's account to `to`.
21
    function transfer(address to, uint256 amount) external returns (bool);
22

                            
                        
23
    /// @notice Returns the remaining number of tokens that `spender` is allowed
24
    /// to spend on behalf of `owner`
25
    function allowance(address owner, address spender) external view returns (uint256);
26

                            
                        
27
    /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
28
    /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
29
    function approve(address spender, uint256 amount) external returns (bool);
30

                            
                        
31
    /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism.
32
    /// `amount` is then deducted from the caller's allowance.
33
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
34

                            
                        
35
    /// @notice Returns the name of the token.
36
    function name() external view returns (string memory);
37

                            
                        
38
    /// @notice Returns the symbol of the token.
39
    function symbol() external view returns (string memory);
40

                            
                        
41
    /// @notice Returns the decimals places of the token.
42
    function decimals() external view returns (uint8);
43
}
44

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2;
3

                            
                        
4
import "./IERC165.sol";
5

                            
                        
6
/// @title ERC-721 Non-Fungible Token Standard
7
/// @dev See https://eips.ethereum.org/EIPS/eip-721
8
/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.
9
interface IERC721 is IERC165 {
10
    /// @dev This emits when ownership of any NFT changes by any mechanism.
11
    /// This event emits when NFTs are created (`from` == 0) and destroyed
12
    /// (`to` == 0). Exception: during contract creation, any number of NFTs
13
    /// may be created and assigned without emitting Transfer. At the time of
14
    /// any transfer, the approved address for that NFT (if any) is reset to none.
15
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
16

                            
                        
17
    /// @dev This emits when the approved address for an NFT is changed or
18
    /// reaffirmed. The zero address indicates there is no approved address.
19
    /// When a Transfer event emits, this also indicates that the approved
20
    /// address for that NFT (if any) is reset to none.
21
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
22

                            
                        
23
    /// @dev This emits when an operator is enabled or disabled for an owner.
24
    /// The operator can manage all NFTs of the owner.
25
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
26

                            
                        
27
    /// @notice Count all NFTs assigned to an owner
28
    /// @dev NFTs assigned to the zero address are considered invalid, and this
29
    /// function throws for queries about the zero address.
30
    /// @param _owner An address for whom to query the balance
31
    /// @return The number of NFTs owned by `_owner`, possibly zero
32
    function balanceOf(address _owner) external view returns (uint256);
33

                            
                        
34
    /// @notice Find the owner of an NFT
35
    /// @dev NFTs assigned to zero address are considered invalid, and queries
36
    /// about them do throw.
37
    /// @param _tokenId The identifier for an NFT
38
    /// @return The address of the owner of the NFT
39
    function ownerOf(uint256 _tokenId) external view returns (address);
40

                            
                        
41
    /// @notice Transfers the ownership of an NFT from one address to another address
42
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
43
    /// operator, or the approved address for this NFT. Throws if `_from` is
44
    /// not the current owner. Throws if `_to` is the zero address. Throws if
45
    /// `_tokenId` is not a valid NFT. When transfer is complete, this function
46
    /// checks if `_to` is a smart contract (code size > 0). If so, it calls
47
    /// `onERC721Received` on `_to` and throws if the return value is not
48
    /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
49
    /// @param _from The current owner of the NFT
50
    /// @param _to The new owner
51
    /// @param _tokenId The NFT to transfer
52
    /// @param data Additional data with no specified format, sent in call to `_to`
53
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;
54

                            
                        
55
    /// @notice Transfers the ownership of an NFT from one address to another address
56
    /// @dev This works identically to the other function with an extra data parameter,
57
    /// except this function just sets data to "".
58
    /// @param _from The current owner of the NFT
59
    /// @param _to The new owner
60
    /// @param _tokenId The NFT to transfer
61
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
62

                            
                        
63
    /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
64
    /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
65
    /// THEY MAY BE PERMANENTLY LOST
66
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
67
    /// operator, or the approved address for this NFT. Throws if `_from` is
68
    /// not the current owner. Throws if `_to` is the zero address. Throws if
69
    /// `_tokenId` is not a valid NFT.
70
    /// @param _from The current owner of the NFT
71
    /// @param _to The new owner
72
    /// @param _tokenId The NFT to transfer
73
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
74

                            
                        
75
    /// @notice Change or reaffirm the approved address for an NFT
76
    /// @dev The zero address indicates there is no approved address.
77
    /// Throws unless `msg.sender` is the current NFT owner, or an authorized
78
    /// operator of the current owner.
79
    /// @param _approved The new approved NFT controller
80
    /// @param _tokenId The NFT to approve
81
    function approve(address _approved, uint256 _tokenId) external payable;
82

                            
                        
83
    /// @notice Enable or disable approval for a third party ("operator") to manage
84
    /// all of `msg.sender`'s assets
85
    /// @dev Emits the ApprovalForAll event. The contract MUST allow
86
    /// multiple operators per owner.
87
    /// @param _operator Address to add to the set of authorized operators
88
    /// @param _approved True if the operator is approved, false to revoke approval
89
    function setApprovalForAll(address _operator, bool _approved) external;
90

                            
                        
91
    /// @notice Get the approved address for a single NFT
92
    /// @dev Throws if `_tokenId` is not a valid NFT.
93
    /// @param _tokenId The NFT to find the approved address for
94
    /// @return The approved address for this NFT, or the zero address if there is none
95
    function getApproved(uint256 _tokenId) external view returns (address);
96

                            
                        
97
    /// @notice Query if an address is an authorized operator for another address
98
    /// @param _owner The address that owns the NFTs
99
    /// @param _operator The address that acts on behalf of the owner
100
    /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
101
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
102
}
103

                            
                        
104
/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
105
interface IERC721TokenReceiver {
106
    /// @notice Handle the receipt of an NFT
107
    /// @dev The ERC721 smart contract calls this function on the recipient
108
    /// after a `transfer`. This function MAY throw to revert and reject the
109
    /// transfer. Return of other than the magic value MUST result in the
110
    /// transaction being reverted.
111
    /// Note: the contract address is always the message sender.
112
    /// @param _operator The address which called `safeTransferFrom` function
113
    /// @param _from The address which previously owned the token
114
    /// @param _tokenId The NFT identifier which is being transferred
115
    /// @param _data Additional data with no specified format
116
    /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
117
    ///  unless throwing
118
    function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data)
119
        external
120
        returns (bytes4);
121
}
122

                            
                        
123
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
124
/// @dev See https://eips.ethereum.org/EIPS/eip-721
125
/// Note: the ERC-165 identifier for this interface is 0x5b5e139f.
126
interface IERC721Metadata is IERC721 {
127
    /// @notice A descriptive name for a collection of NFTs in this contract
128
    function name() external view returns (string memory _name);
129

                            
                        
130
    /// @notice An abbreviated name for NFTs in this contract
131
    function symbol() external view returns (string memory _symbol);
132

                            
                        
133
    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
134
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
135
    /// 3986. The URI may point to a JSON file that conforms to the "ERC721
136
    /// Metadata JSON Schema".
137
    function tokenURI(uint256 _tokenId) external view returns (string memory);
138
}
139

                            
                        
140
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
141
/// @dev See https://eips.ethereum.org/EIPS/eip-721
142
/// Note: the ERC-165 identifier for this interface is 0x780e9d63.
143
interface IERC721Enumerable is IERC721 {
144
    /// @notice Count NFTs tracked by this contract
145
    /// @return A count of valid NFTs tracked by this contract, where each one of
146
    /// them has an assigned and queryable owner not equal to the zero address
147
    function totalSupply() external view returns (uint256);
148

                            
                        
149
    /// @notice Enumerate valid NFTs
150
    /// @dev Throws if `_index` >= `totalSupply()`.
151
    /// @param _index A counter less than `totalSupply()`
152
    /// @return The token identifier for the `_index`th NFT,
153
    /// (sort order not specified)
154
    function tokenByIndex(uint256 _index) external view returns (uint256);
155

                            
                        
156
    /// @notice Enumerate NFTs assigned to an owner
157
    /// @dev Throws if `_index` >= `balanceOf(_owner)` or if
158
    /// `_owner` is the zero address, representing invalid NFTs.
159
    /// @param _owner An address where we are interested in NFTs owned by them
160
    /// @param _index A counter less than `balanceOf(_owner)`
161
    /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
162
    /// (sort order not specified)
163
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
164
}
165

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
pragma experimental ABIEncoderV2;
5

                            
                        
6
interface IMulticall3 {
7
    struct Call {
8
        address target;
9
        bytes callData;
10
    }
11

                            
                        
12
    struct Call3 {
13
        address target;
14
        bool allowFailure;
15
        bytes callData;
16
    }
17

                            
                        
18
    struct Call3Value {
19
        address target;
20
        bool allowFailure;
21
        uint256 value;
22
        bytes callData;
23
    }
24

                            
                        
25
    struct Result {
26
        bool success;
27
        bytes returnData;
28
    }
29

                            
                        
30
    function aggregate(Call[] calldata calls)
31
        external
32
        payable
33
        returns (uint256 blockNumber, bytes[] memory returnData);
34

                            
                        
35
    function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);
36

                            
                        
37
    function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);
38

                            
                        
39
    function blockAndAggregate(Call[] calldata calls)
40
        external
41
        payable
42
        returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
43

                            
                        
44
    function getBasefee() external view returns (uint256 basefee);
45

                            
                        
46
    function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);
47

                            
                        
48
    function getBlockNumber() external view returns (uint256 blockNumber);
49

                            
                        
50
    function getChainId() external view returns (uint256 chainid);
51

                            
                        
52
    function getCurrentBlockCoinbase() external view returns (address coinbase);
53

                            
                        
54
    function getCurrentBlockDifficulty() external view returns (uint256 difficulty);
55

                            
                        
56
    function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);
57

                            
                        
58
    function getCurrentBlockTimestamp() external view returns (uint256 timestamp);
59

                            
                        
60
    function getEthBalance(address addr) external view returns (uint256 balance);
61

                            
                        
62
    function getLastBlockHash() external view returns (bytes32 blockHash);
63

                            
                        
64
    function tryAggregate(bool requireSuccess, Call[] calldata calls)
65
        external
66
        payable
67
        returns (Result[] memory returnData);
68

                            
                        
69
    function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)
70
        external
71
        payable
72
        returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
73
}
74

                            
                        

Lines covered: 0 / 63 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
import {IERC20} from "../interfaces/IERC20.sol";
5

                            
                        
6
/// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production.
7
/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol
8
contract MockERC20 is IERC20 {
9
    /*//////////////////////////////////////////////////////////////
10
                            METADATA STORAGE
11
    //////////////////////////////////////////////////////////////*/
12

                            
                        
13
    string internal _name;
14

                            
                        
15
    string internal _symbol;
16

                            
                        
17
    uint8 internal _decimals;
18

                            
                        
19
    function name() external view override returns (string memory) {
20
        return _name;
21
    }
22

                            
                        
23
    function symbol() external view override returns (string memory) {
24
        return _symbol;
25
    }
26

                            
                        
27
    function decimals() external view override returns (uint8) {
28
        return _decimals;
29
    }
30

                            
                        
31
    /*//////////////////////////////////////////////////////////////
32
                              ERC20 STORAGE
33
    //////////////////////////////////////////////////////////////*/
34

                            
                        
35
    uint256 internal _totalSupply;
36

                            
                        
37
    mapping(address => uint256) internal _balanceOf;
38

                            
                        
39
    mapping(address => mapping(address => uint256)) internal _allowance;
40

                            
                        
41
    function totalSupply() external view override returns (uint256) {
42
        return _totalSupply;
43
    }
44

                            
                        
45
    function balanceOf(address owner) external view override returns (uint256) {
46
        return _balanceOf[owner];
47
    }
48

                            
                        
49
    function allowance(address owner, address spender) external view override returns (uint256) {
50
        return _allowance[owner][spender];
51
    }
52

                            
                        
53
    /*//////////////////////////////////////////////////////////////
54
                            EIP-2612 STORAGE
55
    //////////////////////////////////////////////////////////////*/
56

                            
                        
57
    uint256 internal INITIAL_CHAIN_ID;
58

                            
                        
59
    bytes32 internal INITIAL_DOMAIN_SEPARATOR;
60

                            
                        
61
    mapping(address => uint256) public nonces;
62

                            
                        
63
    /*//////////////////////////////////////////////////////////////
64
                               INITIALIZE
65
    //////////////////////////////////////////////////////////////*/
66

                            
                        
67
    /// @dev A bool to track whether the contract has been initialized.
68
    bool private initialized;
69

                            
                        
70
    /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and
71
    /// syntaxes, we add an initialization function that can be called only once.
72
    function initialize(string memory name_, string memory symbol_, uint8 decimals_) public {
73
        require(!initialized, "ALREADY_INITIALIZED");
74

                            
                        
75
        _name = name_;
76
        _symbol = symbol_;
77
        _decimals = decimals_;
78

                            
                        
79
        INITIAL_CHAIN_ID = _pureChainId();
80
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
81

                            
                        
82
        initialized = true;
83
    }
84

                            
                        
85
    /*//////////////////////////////////////////////////////////////
86
                               ERC20 LOGIC
87
    //////////////////////////////////////////////////////////////*/
88

                            
                        
89
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
90
        _allowance[msg.sender][spender] = amount;
91

                            
                        
92
        emit Approval(msg.sender, spender, amount);
93

                            
                        
94
        return true;
95
    }
96

                            
                        
97
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
98
        _balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount);
99
        _balanceOf[to] = _add(_balanceOf[to], amount);
100

                            
                        
101
        emit Transfer(msg.sender, to, amount);
102

                            
                        
103
        return true;
104
    }
105

                            
                        
106
    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
107
        uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals.
108

                            
                        
109
        if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount);
110

                            
                        
111
        _balanceOf[from] = _sub(_balanceOf[from], amount);
112
        _balanceOf[to] = _add(_balanceOf[to], amount);
113

                            
                        
114
        emit Transfer(from, to, amount);
115

                            
                        
116
        return true;
117
    }
118

                            
                        
119
    /*//////////////////////////////////////////////////////////////
120
                             EIP-2612 LOGIC
121
    //////////////////////////////////////////////////////////////*/
122

                            
                        
123
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
124
        public
125
        virtual
126
    {
127
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
128

                            
                        
129
        address recoveredAddress = ecrecover(
130
            keccak256(
131
                abi.encodePacked(
132
                    "\x19\x01",
133
                    DOMAIN_SEPARATOR(),
134
                    keccak256(
135
                        abi.encode(
136
                            keccak256(
137
                                "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
138
                            ),
139
                            owner,
140
                            spender,
141
                            value,
142
                            nonces[owner]++,
143
                            deadline
144
                        )
145
                    )
146
                )
147
            ),
148
            v,
149
            r,
150
            s
151
        );
152

                            
                        
153
        require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
154

                            
                        
155
        _allowance[recoveredAddress][spender] = value;
156

                            
                        
157
        emit Approval(owner, spender, value);
158
    }
159

                            
                        
160
    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
161
        return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
162
    }
163

                            
                        
164
    function computeDomainSeparator() internal view virtual returns (bytes32) {
165
        return keccak256(
166
            abi.encode(
167
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
168
                keccak256(bytes(_name)),
169
                keccak256("1"),
170
                _pureChainId(),
171
                address(this)
172
            )
173
        );
174
    }
175

                            
                        
176
    /*//////////////////////////////////////////////////////////////
177
                        INTERNAL MINT/BURN LOGIC
178
    //////////////////////////////////////////////////////////////*/
179

                            
                        
180
    function _mint(address to, uint256 amount) internal virtual {
181
        _totalSupply = _add(_totalSupply, amount);
182
        _balanceOf[to] = _add(_balanceOf[to], amount);
183

                            
                        
184
        emit Transfer(address(0), to, amount);
185
    }
186

                            
                        
187
    function _burn(address from, uint256 amount) internal virtual {
188
        _balanceOf[from] = _sub(_balanceOf[from], amount);
189
        _totalSupply = _sub(_totalSupply, amount);
190

                            
                        
191
        emit Transfer(from, address(0), amount);
192
    }
193

                            
                        
194
    /*//////////////////////////////////////////////////////////////
195
                        INTERNAL SAFE MATH LOGIC
196
    //////////////////////////////////////////////////////////////*/
197

                            
                        
198
    function _add(uint256 a, uint256 b) internal pure returns (uint256) {
199
        uint256 c = a + b;
200
        require(c >= a, "ERC20: addition overflow");
201
        return c;
202
    }
203

                            
                        
204
    function _sub(uint256 a, uint256 b) internal pure returns (uint256) {
205
        require(a >= b, "ERC20: subtraction underflow");
206
        return a - b;
207
    }
208

                            
                        
209
    /*//////////////////////////////////////////////////////////////
210
                                HELPERS
211
    //////////////////////////////////////////////////////////////*/
212

                            
                        
213
    // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
214
    // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
215
    // can't simply access the chain ID in a normal view or pure function because the solc View Pure
216
    // Checker changed `chainid` from pure to view in 0.8.0.
217
    function _viewChainId() private view returns (uint256 chainId) {
218
        // Assembly required since `block.chainid` was introduced in 0.8.0.
219
        assembly {
220
            chainId := chainid()
221
        }
222

                            
                        
223
        address(this); // Silence warnings in older Solc versions.
224
    }
225

                            
                        
226
    function _pureChainId() private pure returns (uint256 chainId) {
227
        function() internal view returns (uint256) fnIn = _viewChainId;
228
        function() internal pure returns (uint256) pureChainId;
229
        assembly {
230
            pureChainId := fnIn
231
        }
232
        chainId = pureChainId();
233
    }
234
}
235

                            
                        

Lines covered: 0 / 45 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol";
5

                            
                        
6
/// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production.
7
/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol
8
contract MockERC721 is IERC721Metadata {
9
    /*//////////////////////////////////////////////////////////////
10
                         METADATA STORAGE/LOGIC
11
    //////////////////////////////////////////////////////////////*/
12

                            
                        
13
    string internal _name;
14

                            
                        
15
    string internal _symbol;
16

                            
                        
17
    function name() external view override returns (string memory) {
18
        return _name;
19
    }
20

                            
                        
21
    function symbol() external view override returns (string memory) {
22
        return _symbol;
23
    }
24

                            
                        
25
    function tokenURI(uint256 id) public view virtual override returns (string memory) {}
26

                            
                        
27
    /*//////////////////////////////////////////////////////////////
28
                      ERC721 BALANCE/OWNER STORAGE
29
    //////////////////////////////////////////////////////////////*/
30

                            
                        
31
    mapping(uint256 => address) internal _ownerOf;
32

                            
                        
33
    mapping(address => uint256) internal _balanceOf;
34

                            
                        
35
    function ownerOf(uint256 id) public view virtual override returns (address owner) {
36
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
37
    }
38

                            
                        
39
    function balanceOf(address owner) public view virtual override returns (uint256) {
40
        require(owner != address(0), "ZERO_ADDRESS");
41

                            
                        
42
        return _balanceOf[owner];
43
    }
44

                            
                        
45
    /*//////////////////////////////////////////////////////////////
46
                         ERC721 APPROVAL STORAGE
47
    //////////////////////////////////////////////////////////////*/
48

                            
                        
49
    mapping(uint256 => address) internal _getApproved;
50

                            
                        
51
    mapping(address => mapping(address => bool)) internal _isApprovedForAll;
52

                            
                        
53
    function getApproved(uint256 id) public view virtual override returns (address) {
54
        return _getApproved[id];
55
    }
56

                            
                        
57
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
58
        return _isApprovedForAll[owner][operator];
59
    }
60

                            
                        
61
    /*//////////////////////////////////////////////////////////////
62
                               INITIALIZE
63
    //////////////////////////////////////////////////////////////*/
64

                            
                        
65
    /// @dev A bool to track whether the contract has been initialized.
66
    bool private initialized;
67

                            
                        
68
    /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and
69
    /// syntaxes, we add an initialization function that can be called only once.
70
    function initialize(string memory name_, string memory symbol_) public {
71
        require(!initialized, "ALREADY_INITIALIZED");
72

                            
                        
73
        _name = name_;
74
        _symbol = symbol_;
75

                            
                        
76
        initialized = true;
77
    }
78

                            
                        
79
    /*//////////////////////////////////////////////////////////////
80
                              ERC721 LOGIC
81
    //////////////////////////////////////////////////////////////*/
82

                            
                        
83
    function approve(address spender, uint256 id) public payable virtual override {
84
        address owner = _ownerOf[id];
85

                            
                        
86
        require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
87

                            
                        
88
        _getApproved[id] = spender;
89

                            
                        
90
        emit Approval(owner, spender, id);
91
    }
92

                            
                        
93
    function setApprovalForAll(address operator, bool approved) public virtual override {
94
        _isApprovedForAll[msg.sender][operator] = approved;
95

                            
                        
96
        emit ApprovalForAll(msg.sender, operator, approved);
97
    }
98

                            
                        
99
    function transferFrom(address from, address to, uint256 id) public payable virtual override {
100
        require(from == _ownerOf[id], "WRONG_FROM");
101

                            
                        
102
        require(to != address(0), "INVALID_RECIPIENT");
103

                            
                        
104
        require(
105
            msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id],
106
            "NOT_AUTHORIZED"
107
        );
108

                            
                        
109
        // Underflow of the sender's balance is impossible because we check for
110
        // ownership above and the recipient's balance can't realistically overflow.
111
        _balanceOf[from]--;
112

                            
                        
113
        _balanceOf[to]++;
114

                            
                        
115
        _ownerOf[id] = to;
116

                            
                        
117
        delete _getApproved[id];
118

                            
                        
119
        emit Transfer(from, to, id);
120
    }
121

                            
                        
122
    function safeTransferFrom(address from, address to, uint256 id) public payable virtual override {
123
        transferFrom(from, to, id);
124

                            
                        
125
        require(
126
            !_isContract(to)
127
                || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "")
128
                    == IERC721TokenReceiver.onERC721Received.selector,
129
            "UNSAFE_RECIPIENT"
130
        );
131
    }
132

                            
                        
133
    function safeTransferFrom(address from, address to, uint256 id, bytes memory data)
134
        public
135
        payable
136
        virtual
137
        override
138
    {
139
        transferFrom(from, to, id);
140

                            
                        
141
        require(
142
            !_isContract(to)
143
                || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data)
144
                    == IERC721TokenReceiver.onERC721Received.selector,
145
            "UNSAFE_RECIPIENT"
146
        );
147
    }
148

                            
                        
149
    /*//////////////////////////////////////////////////////////////
150
                              ERC165 LOGIC
151
    //////////////////////////////////////////////////////////////*/
152

                            
                        
153
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
154
        return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165
155
            || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721
156
            || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
157
    }
158

                            
                        
159
    /*//////////////////////////////////////////////////////////////
160
                        INTERNAL MINT/BURN LOGIC
161
    //////////////////////////////////////////////////////////////*/
162

                            
                        
163
    function _mint(address to, uint256 id) internal virtual {
164
        require(to != address(0), "INVALID_RECIPIENT");
165

                            
                        
166
        require(_ownerOf[id] == address(0), "ALREADY_MINTED");
167

                            
                        
168
        // Counter overflow is incredibly unrealistic.
169

                            
                        
170
        _balanceOf[to]++;
171

                            
                        
172
        _ownerOf[id] = to;
173

                            
                        
174
        emit Transfer(address(0), to, id);
175
    }
176

                            
                        
177
    function _burn(uint256 id) internal virtual {
178
        address owner = _ownerOf[id];
179

                            
                        
180
        require(owner != address(0), "NOT_MINTED");
181

                            
                        
182
        _balanceOf[owner]--;
183

                            
                        
184
        delete _ownerOf[id];
185

                            
                        
186
        delete _getApproved[id];
187

                            
                        
188
        emit Transfer(owner, address(0), id);
189
    }
190

                            
                        
191
    /*//////////////////////////////////////////////////////////////
192
                        INTERNAL SAFE MINT LOGIC
193
    //////////////////////////////////////////////////////////////*/
194

                            
                        
195
    function _safeMint(address to, uint256 id) internal virtual {
196
        _mint(to, id);
197

                            
                        
198
        require(
199
            !_isContract(to)
200
                || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "")
201
                    == IERC721TokenReceiver.onERC721Received.selector,
202
            "UNSAFE_RECIPIENT"
203
        );
204
    }
205

                            
                        
206
    function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
207
        _mint(to, id);
208

                            
                        
209
        require(
210
            !_isContract(to)
211
                || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data)
212
                    == IERC721TokenReceiver.onERC721Received.selector,
213
            "UNSAFE_RECIPIENT"
214
        );
215
    }
216

                            
                        
217
    /*//////////////////////////////////////////////////////////////
218
                                HELPERS
219
    //////////////////////////////////////////////////////////////*/
220

                            
                        
221
    function _isContract(address _addr) private view returns (bool) {
222
        uint256 codeLength;
223

                            
                        
224
        // Assembly required for versions < 0.8.0 to check extcodesize.
225
        assembly {
226
            codeLength := extcodesize(_addr)
227
        }
228

                            
                        
229
        return codeLength > 0;
230
    }
231
}
232

                            
                        

Lines covered: 0 / 1 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3

                            
                        
4
/// @author philogy <https://github.com/philogy>
5
/// @dev Code generated automatically by script.
6
library safeconsole {
7
    uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67;
8

                            
                        
9
    // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374)
10
    // for the view-to-pure log trick.
11
    function _sendLogPayload(uint256 offset, uint256 size) private pure {
12
        function(uint256, uint256) internal view fnIn = _sendLogPayloadView;
13
        function(uint256, uint256) internal pure pureSendLogPayload;
14
        /// @solidity memory-safe-assembly
15
        assembly {
16
            pureSendLogPayload := fnIn
17
        }
18
        pureSendLogPayload(offset, size);
19
    }
20

                            
                        
21
    function _sendLogPayloadView(uint256 offset, uint256 size) private view {
22
        /// @solidity memory-safe-assembly
23
        assembly {
24
            pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0))
25
        }
26
    }
27

                            
                        
28
    function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure {
29
        function(uint256, uint256, uint256) internal view fnIn = _memcopyView;
30
        function(uint256, uint256, uint256) internal pure pureMemcopy;
31
        /// @solidity memory-safe-assembly
32
        assembly {
33
            pureMemcopy := fnIn
34
        }
35
        pureMemcopy(fromOffset, toOffset, length);
36
    }
37

                            
                        
38
    function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view {
39
        /// @solidity memory-safe-assembly
40
        assembly {
41
            pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length))
42
        }
43
    }
44

                            
                        
45
    function logMemory(uint256 offset, uint256 length) internal pure {
46
        if (offset >= 0x60) {
47
            // Sufficient memory before slice to prepare call header.
48
            bytes32 m0;
49
            bytes32 m1;
50
            bytes32 m2;
51
            /// @solidity memory-safe-assembly
52
            assembly {
53
                m0 := mload(sub(offset, 0x60))
54
                m1 := mload(sub(offset, 0x40))
55
                m2 := mload(sub(offset, 0x20))
56
                // Selector of `log(bytes)`.
57
                mstore(sub(offset, 0x60), 0x0be77f56)
58
                mstore(sub(offset, 0x40), 0x20)
59
                mstore(sub(offset, 0x20), length)
60
            }
61
            _sendLogPayload(offset - 0x44, length + 0x44);
62
            /// @solidity memory-safe-assembly
63
            assembly {
64
                mstore(sub(offset, 0x60), m0)
65
                mstore(sub(offset, 0x40), m1)
66
                mstore(sub(offset, 0x20), m2)
67
            }
68
        } else {
69
            // Insufficient space, so copy slice forward, add header and reverse.
70
            bytes32 m0;
71
            bytes32 m1;
72
            bytes32 m2;
73
            uint256 endOffset = offset + length;
74
            /// @solidity memory-safe-assembly
75
            assembly {
76
                m0 := mload(add(endOffset, 0x00))
77
                m1 := mload(add(endOffset, 0x20))
78
                m2 := mload(add(endOffset, 0x40))
79
            }
80
            _memcopy(offset, offset + 0x60, length);
81
            /// @solidity memory-safe-assembly
82
            assembly {
83
                // Selector of `log(bytes)`.
84
                mstore(add(offset, 0x00), 0x0be77f56)
85
                mstore(add(offset, 0x20), 0x20)
86
                mstore(add(offset, 0x40), length)
87
            }
88
            _sendLogPayload(offset + 0x1c, length + 0x44);
89
            _memcopy(offset + 0x60, offset, length);
90
            /// @solidity memory-safe-assembly
91
            assembly {
92
                mstore(add(endOffset, 0x00), m0)
93
                mstore(add(endOffset, 0x20), m1)
94
                mstore(add(endOffset, 0x40), m2)
95
            }
96
        }
97
    }
98

                            
                        
99
    function log(address p0) internal pure {
100
        bytes32 m0;
101
        bytes32 m1;
102
        /// @solidity memory-safe-assembly
103
        assembly {
104
            m0 := mload(0x00)
105
            m1 := mload(0x20)
106
            // Selector of `log(address)`.
107
            mstore(0x00, 0x2c2ecbc2)
108
            mstore(0x20, p0)
109
        }
110
        _sendLogPayload(0x1c, 0x24);
111
        /// @solidity memory-safe-assembly
112
        assembly {
113
            mstore(0x00, m0)
114
            mstore(0x20, m1)
115
        }
116
    }
117

                            
                        
118
    function log(bool p0) internal pure {
119
        bytes32 m0;
120
        bytes32 m1;
121
        /// @solidity memory-safe-assembly
122
        assembly {
123
            m0 := mload(0x00)
124
            m1 := mload(0x20)
125
            // Selector of `log(bool)`.
126
            mstore(0x00, 0x32458eed)
127
            mstore(0x20, p0)
128
        }
129
        _sendLogPayload(0x1c, 0x24);
130
        /// @solidity memory-safe-assembly
131
        assembly {
132
            mstore(0x00, m0)
133
            mstore(0x20, m1)
134
        }
135
    }
136

                            
                        
137
    function log(uint256 p0) internal pure {
138
        bytes32 m0;
139
        bytes32 m1;
140
        /// @solidity memory-safe-assembly
141
        assembly {
142
            m0 := mload(0x00)
143
            m1 := mload(0x20)
144
            // Selector of `log(uint256)`.
145
            mstore(0x00, 0xf82c50f1)
146
            mstore(0x20, p0)
147
        }
148
        _sendLogPayload(0x1c, 0x24);
149
        /// @solidity memory-safe-assembly
150
        assembly {
151
            mstore(0x00, m0)
152
            mstore(0x20, m1)
153
        }
154
    }
155

                            
                        
156
    function log(bytes32 p0) internal pure {
157
        bytes32 m0;
158
        bytes32 m1;
159
        bytes32 m2;
160
        bytes32 m3;
161
        /// @solidity memory-safe-assembly
162
        assembly {
163
            function writeString(pos, w) {
164
                let length := 0
165
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
166
                mstore(pos, length)
167
                let shift := sub(256, shl(3, length))
168
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
169
            }
170
            m0 := mload(0x00)
171
            m1 := mload(0x20)
172
            m2 := mload(0x40)
173
            m3 := mload(0x60)
174
            // Selector of `log(string)`.
175
            mstore(0x00, 0x41304fac)
176
            mstore(0x20, 0x20)
177
            writeString(0x40, p0)
178
        }
179
        _sendLogPayload(0x1c, 0x64);
180
        /// @solidity memory-safe-assembly
181
        assembly {
182
            mstore(0x00, m0)
183
            mstore(0x20, m1)
184
            mstore(0x40, m2)
185
            mstore(0x60, m3)
186
        }
187
    }
188

                            
                        
189
    function log(address p0, address p1) internal pure {
190
        bytes32 m0;
191
        bytes32 m1;
192
        bytes32 m2;
193
        /// @solidity memory-safe-assembly
194
        assembly {
195
            m0 := mload(0x00)
196
            m1 := mload(0x20)
197
            m2 := mload(0x40)
198
            // Selector of `log(address,address)`.
199
            mstore(0x00, 0xdaf0d4aa)
200
            mstore(0x20, p0)
201
            mstore(0x40, p1)
202
        }
203
        _sendLogPayload(0x1c, 0x44);
204
        /// @solidity memory-safe-assembly
205
        assembly {
206
            mstore(0x00, m0)
207
            mstore(0x20, m1)
208
            mstore(0x40, m2)
209
        }
210
    }
211

                            
                        
212
    function log(address p0, bool p1) internal pure {
213
        bytes32 m0;
214
        bytes32 m1;
215
        bytes32 m2;
216
        /// @solidity memory-safe-assembly
217
        assembly {
218
            m0 := mload(0x00)
219
            m1 := mload(0x20)
220
            m2 := mload(0x40)
221
            // Selector of `log(address,bool)`.
222
            mstore(0x00, 0x75b605d3)
223
            mstore(0x20, p0)
224
            mstore(0x40, p1)
225
        }
226
        _sendLogPayload(0x1c, 0x44);
227
        /// @solidity memory-safe-assembly
228
        assembly {
229
            mstore(0x00, m0)
230
            mstore(0x20, m1)
231
            mstore(0x40, m2)
232
        }
233
    }
234

                            
                        
235
    function log(address p0, uint256 p1) internal pure {
236
        bytes32 m0;
237
        bytes32 m1;
238
        bytes32 m2;
239
        /// @solidity memory-safe-assembly
240
        assembly {
241
            m0 := mload(0x00)
242
            m1 := mload(0x20)
243
            m2 := mload(0x40)
244
            // Selector of `log(address,uint256)`.
245
            mstore(0x00, 0x8309e8a8)
246
            mstore(0x20, p0)
247
            mstore(0x40, p1)
248
        }
249
        _sendLogPayload(0x1c, 0x44);
250
        /// @solidity memory-safe-assembly
251
        assembly {
252
            mstore(0x00, m0)
253
            mstore(0x20, m1)
254
            mstore(0x40, m2)
255
        }
256
    }
257

                            
                        
258
    function log(address p0, bytes32 p1) internal pure {
259
        bytes32 m0;
260
        bytes32 m1;
261
        bytes32 m2;
262
        bytes32 m3;
263
        bytes32 m4;
264
        /// @solidity memory-safe-assembly
265
        assembly {
266
            function writeString(pos, w) {
267
                let length := 0
268
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
269
                mstore(pos, length)
270
                let shift := sub(256, shl(3, length))
271
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
272
            }
273
            m0 := mload(0x00)
274
            m1 := mload(0x20)
275
            m2 := mload(0x40)
276
            m3 := mload(0x60)
277
            m4 := mload(0x80)
278
            // Selector of `log(address,string)`.
279
            mstore(0x00, 0x759f86bb)
280
            mstore(0x20, p0)
281
            mstore(0x40, 0x40)
282
            writeString(0x60, p1)
283
        }
284
        _sendLogPayload(0x1c, 0x84);
285
        /// @solidity memory-safe-assembly
286
        assembly {
287
            mstore(0x00, m0)
288
            mstore(0x20, m1)
289
            mstore(0x40, m2)
290
            mstore(0x60, m3)
291
            mstore(0x80, m4)
292
        }
293
    }
294

                            
                        
295
    function log(bool p0, address p1) internal pure {
296
        bytes32 m0;
297
        bytes32 m1;
298
        bytes32 m2;
299
        /// @solidity memory-safe-assembly
300
        assembly {
301
            m0 := mload(0x00)
302
            m1 := mload(0x20)
303
            m2 := mload(0x40)
304
            // Selector of `log(bool,address)`.
305
            mstore(0x00, 0x853c4849)
306
            mstore(0x20, p0)
307
            mstore(0x40, p1)
308
        }
309
        _sendLogPayload(0x1c, 0x44);
310
        /// @solidity memory-safe-assembly
311
        assembly {
312
            mstore(0x00, m0)
313
            mstore(0x20, m1)
314
            mstore(0x40, m2)
315
        }
316
    }
317

                            
                        
318
    function log(bool p0, bool p1) internal pure {
319
        bytes32 m0;
320
        bytes32 m1;
321
        bytes32 m2;
322
        /// @solidity memory-safe-assembly
323
        assembly {
324
            m0 := mload(0x00)
325
            m1 := mload(0x20)
326
            m2 := mload(0x40)
327
            // Selector of `log(bool,bool)`.
328
            mstore(0x00, 0x2a110e83)
329
            mstore(0x20, p0)
330
            mstore(0x40, p1)
331
        }
332
        _sendLogPayload(0x1c, 0x44);
333
        /// @solidity memory-safe-assembly
334
        assembly {
335
            mstore(0x00, m0)
336
            mstore(0x20, m1)
337
            mstore(0x40, m2)
338
        }
339
    }
340

                            
                        
341
    function log(bool p0, uint256 p1) internal pure {
342
        bytes32 m0;
343
        bytes32 m1;
344
        bytes32 m2;
345
        /// @solidity memory-safe-assembly
346
        assembly {
347
            m0 := mload(0x00)
348
            m1 := mload(0x20)
349
            m2 := mload(0x40)
350
            // Selector of `log(bool,uint256)`.
351
            mstore(0x00, 0x399174d3)
352
            mstore(0x20, p0)
353
            mstore(0x40, p1)
354
        }
355
        _sendLogPayload(0x1c, 0x44);
356
        /// @solidity memory-safe-assembly
357
        assembly {
358
            mstore(0x00, m0)
359
            mstore(0x20, m1)
360
            mstore(0x40, m2)
361
        }
362
    }
363

                            
                        
364
    function log(bool p0, bytes32 p1) internal pure {
365
        bytes32 m0;
366
        bytes32 m1;
367
        bytes32 m2;
368
        bytes32 m3;
369
        bytes32 m4;
370
        /// @solidity memory-safe-assembly
371
        assembly {
372
            function writeString(pos, w) {
373
                let length := 0
374
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
375
                mstore(pos, length)
376
                let shift := sub(256, shl(3, length))
377
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
378
            }
379
            m0 := mload(0x00)
380
            m1 := mload(0x20)
381
            m2 := mload(0x40)
382
            m3 := mload(0x60)
383
            m4 := mload(0x80)
384
            // Selector of `log(bool,string)`.
385
            mstore(0x00, 0x8feac525)
386
            mstore(0x20, p0)
387
            mstore(0x40, 0x40)
388
            writeString(0x60, p1)
389
        }
390
        _sendLogPayload(0x1c, 0x84);
391
        /// @solidity memory-safe-assembly
392
        assembly {
393
            mstore(0x00, m0)
394
            mstore(0x20, m1)
395
            mstore(0x40, m2)
396
            mstore(0x60, m3)
397
            mstore(0x80, m4)
398
        }
399
    }
400

                            
                        
401
    function log(uint256 p0, address p1) internal pure {
402
        bytes32 m0;
403
        bytes32 m1;
404
        bytes32 m2;
405
        /// @solidity memory-safe-assembly
406
        assembly {
407
            m0 := mload(0x00)
408
            m1 := mload(0x20)
409
            m2 := mload(0x40)
410
            // Selector of `log(uint256,address)`.
411
            mstore(0x00, 0x69276c86)
412
            mstore(0x20, p0)
413
            mstore(0x40, p1)
414
        }
415
        _sendLogPayload(0x1c, 0x44);
416
        /// @solidity memory-safe-assembly
417
        assembly {
418
            mstore(0x00, m0)
419
            mstore(0x20, m1)
420
            mstore(0x40, m2)
421
        }
422
    }
423

                            
                        
424
    function log(uint256 p0, bool p1) internal pure {
425
        bytes32 m0;
426
        bytes32 m1;
427
        bytes32 m2;
428
        /// @solidity memory-safe-assembly
429
        assembly {
430
            m0 := mload(0x00)
431
            m1 := mload(0x20)
432
            m2 := mload(0x40)
433
            // Selector of `log(uint256,bool)`.
434
            mstore(0x00, 0x1c9d7eb3)
435
            mstore(0x20, p0)
436
            mstore(0x40, p1)
437
        }
438
        _sendLogPayload(0x1c, 0x44);
439
        /// @solidity memory-safe-assembly
440
        assembly {
441
            mstore(0x00, m0)
442
            mstore(0x20, m1)
443
            mstore(0x40, m2)
444
        }
445
    }
446

                            
                        
447
    function log(uint256 p0, uint256 p1) internal pure {
448
        bytes32 m0;
449
        bytes32 m1;
450
        bytes32 m2;
451
        /// @solidity memory-safe-assembly
452
        assembly {
453
            m0 := mload(0x00)
454
            m1 := mload(0x20)
455
            m2 := mload(0x40)
456
            // Selector of `log(uint256,uint256)`.
457
            mstore(0x00, 0xf666715a)
458
            mstore(0x20, p0)
459
            mstore(0x40, p1)
460
        }
461
        _sendLogPayload(0x1c, 0x44);
462
        /// @solidity memory-safe-assembly
463
        assembly {
464
            mstore(0x00, m0)
465
            mstore(0x20, m1)
466
            mstore(0x40, m2)
467
        }
468
    }
469

                            
                        
470
    function log(uint256 p0, bytes32 p1) internal pure {
471
        bytes32 m0;
472
        bytes32 m1;
473
        bytes32 m2;
474
        bytes32 m3;
475
        bytes32 m4;
476
        /// @solidity memory-safe-assembly
477
        assembly {
478
            function writeString(pos, w) {
479
                let length := 0
480
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
481
                mstore(pos, length)
482
                let shift := sub(256, shl(3, length))
483
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
484
            }
485
            m0 := mload(0x00)
486
            m1 := mload(0x20)
487
            m2 := mload(0x40)
488
            m3 := mload(0x60)
489
            m4 := mload(0x80)
490
            // Selector of `log(uint256,string)`.
491
            mstore(0x00, 0x643fd0df)
492
            mstore(0x20, p0)
493
            mstore(0x40, 0x40)
494
            writeString(0x60, p1)
495
        }
496
        _sendLogPayload(0x1c, 0x84);
497
        /// @solidity memory-safe-assembly
498
        assembly {
499
            mstore(0x00, m0)
500
            mstore(0x20, m1)
501
            mstore(0x40, m2)
502
            mstore(0x60, m3)
503
            mstore(0x80, m4)
504
        }
505
    }
506

                            
                        
507
    function log(bytes32 p0, address p1) internal pure {
508
        bytes32 m0;
509
        bytes32 m1;
510
        bytes32 m2;
511
        bytes32 m3;
512
        bytes32 m4;
513
        /// @solidity memory-safe-assembly
514
        assembly {
515
            function writeString(pos, w) {
516
                let length := 0
517
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
518
                mstore(pos, length)
519
                let shift := sub(256, shl(3, length))
520
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
521
            }
522
            m0 := mload(0x00)
523
            m1 := mload(0x20)
524
            m2 := mload(0x40)
525
            m3 := mload(0x60)
526
            m4 := mload(0x80)
527
            // Selector of `log(string,address)`.
528
            mstore(0x00, 0x319af333)
529
            mstore(0x20, 0x40)
530
            mstore(0x40, p1)
531
            writeString(0x60, p0)
532
        }
533
        _sendLogPayload(0x1c, 0x84);
534
        /// @solidity memory-safe-assembly
535
        assembly {
536
            mstore(0x00, m0)
537
            mstore(0x20, m1)
538
            mstore(0x40, m2)
539
            mstore(0x60, m3)
540
            mstore(0x80, m4)
541
        }
542
    }
543

                            
                        
544
    function log(bytes32 p0, bool p1) internal pure {
545
        bytes32 m0;
546
        bytes32 m1;
547
        bytes32 m2;
548
        bytes32 m3;
549
        bytes32 m4;
550
        /// @solidity memory-safe-assembly
551
        assembly {
552
            function writeString(pos, w) {
553
                let length := 0
554
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
555
                mstore(pos, length)
556
                let shift := sub(256, shl(3, length))
557
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
558
            }
559
            m0 := mload(0x00)
560
            m1 := mload(0x20)
561
            m2 := mload(0x40)
562
            m3 := mload(0x60)
563
            m4 := mload(0x80)
564
            // Selector of `log(string,bool)`.
565
            mstore(0x00, 0xc3b55635)
566
            mstore(0x20, 0x40)
567
            mstore(0x40, p1)
568
            writeString(0x60, p0)
569
        }
570
        _sendLogPayload(0x1c, 0x84);
571
        /// @solidity memory-safe-assembly
572
        assembly {
573
            mstore(0x00, m0)
574
            mstore(0x20, m1)
575
            mstore(0x40, m2)
576
            mstore(0x60, m3)
577
            mstore(0x80, m4)
578
        }
579
    }
580

                            
                        
581
    function log(bytes32 p0, uint256 p1) internal pure {
582
        bytes32 m0;
583
        bytes32 m1;
584
        bytes32 m2;
585
        bytes32 m3;
586
        bytes32 m4;
587
        /// @solidity memory-safe-assembly
588
        assembly {
589
            function writeString(pos, w) {
590
                let length := 0
591
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
592
                mstore(pos, length)
593
                let shift := sub(256, shl(3, length))
594
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
595
            }
596
            m0 := mload(0x00)
597
            m1 := mload(0x20)
598
            m2 := mload(0x40)
599
            m3 := mload(0x60)
600
            m4 := mload(0x80)
601
            // Selector of `log(string,uint256)`.
602
            mstore(0x00, 0xb60e72cc)
603
            mstore(0x20, 0x40)
604
            mstore(0x40, p1)
605
            writeString(0x60, p0)
606
        }
607
        _sendLogPayload(0x1c, 0x84);
608
        /// @solidity memory-safe-assembly
609
        assembly {
610
            mstore(0x00, m0)
611
            mstore(0x20, m1)
612
            mstore(0x40, m2)
613
            mstore(0x60, m3)
614
            mstore(0x80, m4)
615
        }
616
    }
617

                            
                        
618
    function log(bytes32 p0, bytes32 p1) internal pure {
619
        bytes32 m0;
620
        bytes32 m1;
621
        bytes32 m2;
622
        bytes32 m3;
623
        bytes32 m4;
624
        bytes32 m5;
625
        bytes32 m6;
626
        /// @solidity memory-safe-assembly
627
        assembly {
628
            function writeString(pos, w) {
629
                let length := 0
630
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
631
                mstore(pos, length)
632
                let shift := sub(256, shl(3, length))
633
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
634
            }
635
            m0 := mload(0x00)
636
            m1 := mload(0x20)
637
            m2 := mload(0x40)
638
            m3 := mload(0x60)
639
            m4 := mload(0x80)
640
            m5 := mload(0xa0)
641
            m6 := mload(0xc0)
642
            // Selector of `log(string,string)`.
643
            mstore(0x00, 0x4b5c4277)
644
            mstore(0x20, 0x40)
645
            mstore(0x40, 0x80)
646
            writeString(0x60, p0)
647
            writeString(0xa0, p1)
648
        }
649
        _sendLogPayload(0x1c, 0xc4);
650
        /// @solidity memory-safe-assembly
651
        assembly {
652
            mstore(0x00, m0)
653
            mstore(0x20, m1)
654
            mstore(0x40, m2)
655
            mstore(0x60, m3)
656
            mstore(0x80, m4)
657
            mstore(0xa0, m5)
658
            mstore(0xc0, m6)
659
        }
660
    }
661

                            
                        
662
    function log(address p0, address p1, address p2) internal pure {
663
        bytes32 m0;
664
        bytes32 m1;
665
        bytes32 m2;
666
        bytes32 m3;
667
        /// @solidity memory-safe-assembly
668
        assembly {
669
            m0 := mload(0x00)
670
            m1 := mload(0x20)
671
            m2 := mload(0x40)
672
            m3 := mload(0x60)
673
            // Selector of `log(address,address,address)`.
674
            mstore(0x00, 0x018c84c2)
675
            mstore(0x20, p0)
676
            mstore(0x40, p1)
677
            mstore(0x60, p2)
678
        }
679
        _sendLogPayload(0x1c, 0x64);
680
        /// @solidity memory-safe-assembly
681
        assembly {
682
            mstore(0x00, m0)
683
            mstore(0x20, m1)
684
            mstore(0x40, m2)
685
            mstore(0x60, m3)
686
        }
687
    }
688

                            
                        
689
    function log(address p0, address p1, bool p2) internal pure {
690
        bytes32 m0;
691
        bytes32 m1;
692
        bytes32 m2;
693
        bytes32 m3;
694
        /// @solidity memory-safe-assembly
695
        assembly {
696
            m0 := mload(0x00)
697
            m1 := mload(0x20)
698
            m2 := mload(0x40)
699
            m3 := mload(0x60)
700
            // Selector of `log(address,address,bool)`.
701
            mstore(0x00, 0xf2a66286)
702
            mstore(0x20, p0)
703
            mstore(0x40, p1)
704
            mstore(0x60, p2)
705
        }
706
        _sendLogPayload(0x1c, 0x64);
707
        /// @solidity memory-safe-assembly
708
        assembly {
709
            mstore(0x00, m0)
710
            mstore(0x20, m1)
711
            mstore(0x40, m2)
712
            mstore(0x60, m3)
713
        }
714
    }
715

                            
                        
716
    function log(address p0, address p1, uint256 p2) internal pure {
717
        bytes32 m0;
718
        bytes32 m1;
719
        bytes32 m2;
720
        bytes32 m3;
721
        /// @solidity memory-safe-assembly
722
        assembly {
723
            m0 := mload(0x00)
724
            m1 := mload(0x20)
725
            m2 := mload(0x40)
726
            m3 := mload(0x60)
727
            // Selector of `log(address,address,uint256)`.
728
            mstore(0x00, 0x17fe6185)
729
            mstore(0x20, p0)
730
            mstore(0x40, p1)
731
            mstore(0x60, p2)
732
        }
733
        _sendLogPayload(0x1c, 0x64);
734
        /// @solidity memory-safe-assembly
735
        assembly {
736
            mstore(0x00, m0)
737
            mstore(0x20, m1)
738
            mstore(0x40, m2)
739
            mstore(0x60, m3)
740
        }
741
    }
742

                            
                        
743
    function log(address p0, address p1, bytes32 p2) internal pure {
744
        bytes32 m0;
745
        bytes32 m1;
746
        bytes32 m2;
747
        bytes32 m3;
748
        bytes32 m4;
749
        bytes32 m5;
750
        /// @solidity memory-safe-assembly
751
        assembly {
752
            function writeString(pos, w) {
753
                let length := 0
754
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
755
                mstore(pos, length)
756
                let shift := sub(256, shl(3, length))
757
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
758
            }
759
            m0 := mload(0x00)
760
            m1 := mload(0x20)
761
            m2 := mload(0x40)
762
            m3 := mload(0x60)
763
            m4 := mload(0x80)
764
            m5 := mload(0xa0)
765
            // Selector of `log(address,address,string)`.
766
            mstore(0x00, 0x007150be)
767
            mstore(0x20, p0)
768
            mstore(0x40, p1)
769
            mstore(0x60, 0x60)
770
            writeString(0x80, p2)
771
        }
772
        _sendLogPayload(0x1c, 0xa4);
773
        /// @solidity memory-safe-assembly
774
        assembly {
775
            mstore(0x00, m0)
776
            mstore(0x20, m1)
777
            mstore(0x40, m2)
778
            mstore(0x60, m3)
779
            mstore(0x80, m4)
780
            mstore(0xa0, m5)
781
        }
782
    }
783

                            
                        
784
    function log(address p0, bool p1, address p2) internal pure {
785
        bytes32 m0;
786
        bytes32 m1;
787
        bytes32 m2;
788
        bytes32 m3;
789
        /// @solidity memory-safe-assembly
790
        assembly {
791
            m0 := mload(0x00)
792
            m1 := mload(0x20)
793
            m2 := mload(0x40)
794
            m3 := mload(0x60)
795
            // Selector of `log(address,bool,address)`.
796
            mstore(0x00, 0xf11699ed)
797
            mstore(0x20, p0)
798
            mstore(0x40, p1)
799
            mstore(0x60, p2)
800
        }
801
        _sendLogPayload(0x1c, 0x64);
802
        /// @solidity memory-safe-assembly
803
        assembly {
804
            mstore(0x00, m0)
805
            mstore(0x20, m1)
806
            mstore(0x40, m2)
807
            mstore(0x60, m3)
808
        }
809
    }
810

                            
                        
811
    function log(address p0, bool p1, bool p2) internal pure {
812
        bytes32 m0;
813
        bytes32 m1;
814
        bytes32 m2;
815
        bytes32 m3;
816
        /// @solidity memory-safe-assembly
817
        assembly {
818
            m0 := mload(0x00)
819
            m1 := mload(0x20)
820
            m2 := mload(0x40)
821
            m3 := mload(0x60)
822
            // Selector of `log(address,bool,bool)`.
823
            mstore(0x00, 0xeb830c92)
824
            mstore(0x20, p0)
825
            mstore(0x40, p1)
826
            mstore(0x60, p2)
827
        }
828
        _sendLogPayload(0x1c, 0x64);
829
        /// @solidity memory-safe-assembly
830
        assembly {
831
            mstore(0x00, m0)
832
            mstore(0x20, m1)
833
            mstore(0x40, m2)
834
            mstore(0x60, m3)
835
        }
836
    }
837

                            
                        
838
    function log(address p0, bool p1, uint256 p2) internal pure {
839
        bytes32 m0;
840
        bytes32 m1;
841
        bytes32 m2;
842
        bytes32 m3;
843
        /// @solidity memory-safe-assembly
844
        assembly {
845
            m0 := mload(0x00)
846
            m1 := mload(0x20)
847
            m2 := mload(0x40)
848
            m3 := mload(0x60)
849
            // Selector of `log(address,bool,uint256)`.
850
            mstore(0x00, 0x9c4f99fb)
851
            mstore(0x20, p0)
852
            mstore(0x40, p1)
853
            mstore(0x60, p2)
854
        }
855
        _sendLogPayload(0x1c, 0x64);
856
        /// @solidity memory-safe-assembly
857
        assembly {
858
            mstore(0x00, m0)
859
            mstore(0x20, m1)
860
            mstore(0x40, m2)
861
            mstore(0x60, m3)
862
        }
863
    }
864

                            
                        
865
    function log(address p0, bool p1, bytes32 p2) internal pure {
866
        bytes32 m0;
867
        bytes32 m1;
868
        bytes32 m2;
869
        bytes32 m3;
870
        bytes32 m4;
871
        bytes32 m5;
872
        /// @solidity memory-safe-assembly
873
        assembly {
874
            function writeString(pos, w) {
875
                let length := 0
876
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
877
                mstore(pos, length)
878
                let shift := sub(256, shl(3, length))
879
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
880
            }
881
            m0 := mload(0x00)
882
            m1 := mload(0x20)
883
            m2 := mload(0x40)
884
            m3 := mload(0x60)
885
            m4 := mload(0x80)
886
            m5 := mload(0xa0)
887
            // Selector of `log(address,bool,string)`.
888
            mstore(0x00, 0x212255cc)
889
            mstore(0x20, p0)
890
            mstore(0x40, p1)
891
            mstore(0x60, 0x60)
892
            writeString(0x80, p2)
893
        }
894
        _sendLogPayload(0x1c, 0xa4);
895
        /// @solidity memory-safe-assembly
896
        assembly {
897
            mstore(0x00, m0)
898
            mstore(0x20, m1)
899
            mstore(0x40, m2)
900
            mstore(0x60, m3)
901
            mstore(0x80, m4)
902
            mstore(0xa0, m5)
903
        }
904
    }
905

                            
                        
906
    function log(address p0, uint256 p1, address p2) internal pure {
907
        bytes32 m0;
908
        bytes32 m1;
909
        bytes32 m2;
910
        bytes32 m3;
911
        /// @solidity memory-safe-assembly
912
        assembly {
913
            m0 := mload(0x00)
914
            m1 := mload(0x20)
915
            m2 := mload(0x40)
916
            m3 := mload(0x60)
917
            // Selector of `log(address,uint256,address)`.
918
            mstore(0x00, 0x7bc0d848)
919
            mstore(0x20, p0)
920
            mstore(0x40, p1)
921
            mstore(0x60, p2)
922
        }
923
        _sendLogPayload(0x1c, 0x64);
924
        /// @solidity memory-safe-assembly
925
        assembly {
926
            mstore(0x00, m0)
927
            mstore(0x20, m1)
928
            mstore(0x40, m2)
929
            mstore(0x60, m3)
930
        }
931
    }
932

                            
                        
933
    function log(address p0, uint256 p1, bool p2) internal pure {
934
        bytes32 m0;
935
        bytes32 m1;
936
        bytes32 m2;
937
        bytes32 m3;
938
        /// @solidity memory-safe-assembly
939
        assembly {
940
            m0 := mload(0x00)
941
            m1 := mload(0x20)
942
            m2 := mload(0x40)
943
            m3 := mload(0x60)
944
            // Selector of `log(address,uint256,bool)`.
945
            mstore(0x00, 0x678209a8)
946
            mstore(0x20, p0)
947
            mstore(0x40, p1)
948
            mstore(0x60, p2)
949
        }
950
        _sendLogPayload(0x1c, 0x64);
951
        /// @solidity memory-safe-assembly
952
        assembly {
953
            mstore(0x00, m0)
954
            mstore(0x20, m1)
955
            mstore(0x40, m2)
956
            mstore(0x60, m3)
957
        }
958
    }
959

                            
                        
960
    function log(address p0, uint256 p1, uint256 p2) internal pure {
961
        bytes32 m0;
962
        bytes32 m1;
963
        bytes32 m2;
964
        bytes32 m3;
965
        /// @solidity memory-safe-assembly
966
        assembly {
967
            m0 := mload(0x00)
968
            m1 := mload(0x20)
969
            m2 := mload(0x40)
970
            m3 := mload(0x60)
971
            // Selector of `log(address,uint256,uint256)`.
972
            mstore(0x00, 0xb69bcaf6)
973
            mstore(0x20, p0)
974
            mstore(0x40, p1)
975
            mstore(0x60, p2)
976
        }
977
        _sendLogPayload(0x1c, 0x64);
978
        /// @solidity memory-safe-assembly
979
        assembly {
980
            mstore(0x00, m0)
981
            mstore(0x20, m1)
982
            mstore(0x40, m2)
983
            mstore(0x60, m3)
984
        }
985
    }
986

                            
                        
987
    function log(address p0, uint256 p1, bytes32 p2) internal pure {
988
        bytes32 m0;
989
        bytes32 m1;
990
        bytes32 m2;
991
        bytes32 m3;
992
        bytes32 m4;
993
        bytes32 m5;
994
        /// @solidity memory-safe-assembly
995
        assembly {
996
            function writeString(pos, w) {
997
                let length := 0
998
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
999
                mstore(pos, length)
1000
                let shift := sub(256, shl(3, length))
1001
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1002
            }
1003
            m0 := mload(0x00)
1004
            m1 := mload(0x20)
1005
            m2 := mload(0x40)
1006
            m3 := mload(0x60)
1007
            m4 := mload(0x80)
1008
            m5 := mload(0xa0)
1009
            // Selector of `log(address,uint256,string)`.
1010
            mstore(0x00, 0xa1f2e8aa)
1011
            mstore(0x20, p0)
1012
            mstore(0x40, p1)
1013
            mstore(0x60, 0x60)
1014
            writeString(0x80, p2)
1015
        }
1016
        _sendLogPayload(0x1c, 0xa4);
1017
        /// @solidity memory-safe-assembly
1018
        assembly {
1019
            mstore(0x00, m0)
1020
            mstore(0x20, m1)
1021
            mstore(0x40, m2)
1022
            mstore(0x60, m3)
1023
            mstore(0x80, m4)
1024
            mstore(0xa0, m5)
1025
        }
1026
    }
1027

                            
                        
1028
    function log(address p0, bytes32 p1, address p2) internal pure {
1029
        bytes32 m0;
1030
        bytes32 m1;
1031
        bytes32 m2;
1032
        bytes32 m3;
1033
        bytes32 m4;
1034
        bytes32 m5;
1035
        /// @solidity memory-safe-assembly
1036
        assembly {
1037
            function writeString(pos, w) {
1038
                let length := 0
1039
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1040
                mstore(pos, length)
1041
                let shift := sub(256, shl(3, length))
1042
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1043
            }
1044
            m0 := mload(0x00)
1045
            m1 := mload(0x20)
1046
            m2 := mload(0x40)
1047
            m3 := mload(0x60)
1048
            m4 := mload(0x80)
1049
            m5 := mload(0xa0)
1050
            // Selector of `log(address,string,address)`.
1051
            mstore(0x00, 0xf08744e8)
1052
            mstore(0x20, p0)
1053
            mstore(0x40, 0x60)
1054
            mstore(0x60, p2)
1055
            writeString(0x80, p1)
1056
        }
1057
        _sendLogPayload(0x1c, 0xa4);
1058
        /// @solidity memory-safe-assembly
1059
        assembly {
1060
            mstore(0x00, m0)
1061
            mstore(0x20, m1)
1062
            mstore(0x40, m2)
1063
            mstore(0x60, m3)
1064
            mstore(0x80, m4)
1065
            mstore(0xa0, m5)
1066
        }
1067
    }
1068

                            
                        
1069
    function log(address p0, bytes32 p1, bool p2) internal pure {
1070
        bytes32 m0;
1071
        bytes32 m1;
1072
        bytes32 m2;
1073
        bytes32 m3;
1074
        bytes32 m4;
1075
        bytes32 m5;
1076
        /// @solidity memory-safe-assembly
1077
        assembly {
1078
            function writeString(pos, w) {
1079
                let length := 0
1080
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1081
                mstore(pos, length)
1082
                let shift := sub(256, shl(3, length))
1083
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1084
            }
1085
            m0 := mload(0x00)
1086
            m1 := mload(0x20)
1087
            m2 := mload(0x40)
1088
            m3 := mload(0x60)
1089
            m4 := mload(0x80)
1090
            m5 := mload(0xa0)
1091
            // Selector of `log(address,string,bool)`.
1092
            mstore(0x00, 0xcf020fb1)
1093
            mstore(0x20, p0)
1094
            mstore(0x40, 0x60)
1095
            mstore(0x60, p2)
1096
            writeString(0x80, p1)
1097
        }
1098
        _sendLogPayload(0x1c, 0xa4);
1099
        /// @solidity memory-safe-assembly
1100
        assembly {
1101
            mstore(0x00, m0)
1102
            mstore(0x20, m1)
1103
            mstore(0x40, m2)
1104
            mstore(0x60, m3)
1105
            mstore(0x80, m4)
1106
            mstore(0xa0, m5)
1107
        }
1108
    }
1109

                            
                        
1110
    function log(address p0, bytes32 p1, uint256 p2) internal pure {
1111
        bytes32 m0;
1112
        bytes32 m1;
1113
        bytes32 m2;
1114
        bytes32 m3;
1115
        bytes32 m4;
1116
        bytes32 m5;
1117
        /// @solidity memory-safe-assembly
1118
        assembly {
1119
            function writeString(pos, w) {
1120
                let length := 0
1121
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1122
                mstore(pos, length)
1123
                let shift := sub(256, shl(3, length))
1124
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1125
            }
1126
            m0 := mload(0x00)
1127
            m1 := mload(0x20)
1128
            m2 := mload(0x40)
1129
            m3 := mload(0x60)
1130
            m4 := mload(0x80)
1131
            m5 := mload(0xa0)
1132
            // Selector of `log(address,string,uint256)`.
1133
            mstore(0x00, 0x67dd6ff1)
1134
            mstore(0x20, p0)
1135
            mstore(0x40, 0x60)
1136
            mstore(0x60, p2)
1137
            writeString(0x80, p1)
1138
        }
1139
        _sendLogPayload(0x1c, 0xa4);
1140
        /// @solidity memory-safe-assembly
1141
        assembly {
1142
            mstore(0x00, m0)
1143
            mstore(0x20, m1)
1144
            mstore(0x40, m2)
1145
            mstore(0x60, m3)
1146
            mstore(0x80, m4)
1147
            mstore(0xa0, m5)
1148
        }
1149
    }
1150

                            
                        
1151
    function log(address p0, bytes32 p1, bytes32 p2) internal pure {
1152
        bytes32 m0;
1153
        bytes32 m1;
1154
        bytes32 m2;
1155
        bytes32 m3;
1156
        bytes32 m4;
1157
        bytes32 m5;
1158
        bytes32 m6;
1159
        bytes32 m7;
1160
        /// @solidity memory-safe-assembly
1161
        assembly {
1162
            function writeString(pos, w) {
1163
                let length := 0
1164
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1165
                mstore(pos, length)
1166
                let shift := sub(256, shl(3, length))
1167
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1168
            }
1169
            m0 := mload(0x00)
1170
            m1 := mload(0x20)
1171
            m2 := mload(0x40)
1172
            m3 := mload(0x60)
1173
            m4 := mload(0x80)
1174
            m5 := mload(0xa0)
1175
            m6 := mload(0xc0)
1176
            m7 := mload(0xe0)
1177
            // Selector of `log(address,string,string)`.
1178
            mstore(0x00, 0xfb772265)
1179
            mstore(0x20, p0)
1180
            mstore(0x40, 0x60)
1181
            mstore(0x60, 0xa0)
1182
            writeString(0x80, p1)
1183
            writeString(0xc0, p2)
1184
        }
1185
        _sendLogPayload(0x1c, 0xe4);
1186
        /// @solidity memory-safe-assembly
1187
        assembly {
1188
            mstore(0x00, m0)
1189
            mstore(0x20, m1)
1190
            mstore(0x40, m2)
1191
            mstore(0x60, m3)
1192
            mstore(0x80, m4)
1193
            mstore(0xa0, m5)
1194
            mstore(0xc0, m6)
1195
            mstore(0xe0, m7)
1196
        }
1197
    }
1198

                            
                        
1199
    function log(bool p0, address p1, address p2) internal pure {
1200
        bytes32 m0;
1201
        bytes32 m1;
1202
        bytes32 m2;
1203
        bytes32 m3;
1204
        /// @solidity memory-safe-assembly
1205
        assembly {
1206
            m0 := mload(0x00)
1207
            m1 := mload(0x20)
1208
            m2 := mload(0x40)
1209
            m3 := mload(0x60)
1210
            // Selector of `log(bool,address,address)`.
1211
            mstore(0x00, 0xd2763667)
1212
            mstore(0x20, p0)
1213
            mstore(0x40, p1)
1214
            mstore(0x60, p2)
1215
        }
1216
        _sendLogPayload(0x1c, 0x64);
1217
        /// @solidity memory-safe-assembly
1218
        assembly {
1219
            mstore(0x00, m0)
1220
            mstore(0x20, m1)
1221
            mstore(0x40, m2)
1222
            mstore(0x60, m3)
1223
        }
1224
    }
1225

                            
                        
1226
    function log(bool p0, address p1, bool p2) internal pure {
1227
        bytes32 m0;
1228
        bytes32 m1;
1229
        bytes32 m2;
1230
        bytes32 m3;
1231
        /// @solidity memory-safe-assembly
1232
        assembly {
1233
            m0 := mload(0x00)
1234
            m1 := mload(0x20)
1235
            m2 := mload(0x40)
1236
            m3 := mload(0x60)
1237
            // Selector of `log(bool,address,bool)`.
1238
            mstore(0x00, 0x18c9c746)
1239
            mstore(0x20, p0)
1240
            mstore(0x40, p1)
1241
            mstore(0x60, p2)
1242
        }
1243
        _sendLogPayload(0x1c, 0x64);
1244
        /// @solidity memory-safe-assembly
1245
        assembly {
1246
            mstore(0x00, m0)
1247
            mstore(0x20, m1)
1248
            mstore(0x40, m2)
1249
            mstore(0x60, m3)
1250
        }
1251
    }
1252

                            
                        
1253
    function log(bool p0, address p1, uint256 p2) internal pure {
1254
        bytes32 m0;
1255
        bytes32 m1;
1256
        bytes32 m2;
1257
        bytes32 m3;
1258
        /// @solidity memory-safe-assembly
1259
        assembly {
1260
            m0 := mload(0x00)
1261
            m1 := mload(0x20)
1262
            m2 := mload(0x40)
1263
            m3 := mload(0x60)
1264
            // Selector of `log(bool,address,uint256)`.
1265
            mstore(0x00, 0x5f7b9afb)
1266
            mstore(0x20, p0)
1267
            mstore(0x40, p1)
1268
            mstore(0x60, p2)
1269
        }
1270
        _sendLogPayload(0x1c, 0x64);
1271
        /// @solidity memory-safe-assembly
1272
        assembly {
1273
            mstore(0x00, m0)
1274
            mstore(0x20, m1)
1275
            mstore(0x40, m2)
1276
            mstore(0x60, m3)
1277
        }
1278
    }
1279

                            
                        
1280
    function log(bool p0, address p1, bytes32 p2) internal pure {
1281
        bytes32 m0;
1282
        bytes32 m1;
1283
        bytes32 m2;
1284
        bytes32 m3;
1285
        bytes32 m4;
1286
        bytes32 m5;
1287
        /// @solidity memory-safe-assembly
1288
        assembly {
1289
            function writeString(pos, w) {
1290
                let length := 0
1291
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1292
                mstore(pos, length)
1293
                let shift := sub(256, shl(3, length))
1294
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1295
            }
1296
            m0 := mload(0x00)
1297
            m1 := mload(0x20)
1298
            m2 := mload(0x40)
1299
            m3 := mload(0x60)
1300
            m4 := mload(0x80)
1301
            m5 := mload(0xa0)
1302
            // Selector of `log(bool,address,string)`.
1303
            mstore(0x00, 0xde9a9270)
1304
            mstore(0x20, p0)
1305
            mstore(0x40, p1)
1306
            mstore(0x60, 0x60)
1307
            writeString(0x80, p2)
1308
        }
1309
        _sendLogPayload(0x1c, 0xa4);
1310
        /// @solidity memory-safe-assembly
1311
        assembly {
1312
            mstore(0x00, m0)
1313
            mstore(0x20, m1)
1314
            mstore(0x40, m2)
1315
            mstore(0x60, m3)
1316
            mstore(0x80, m4)
1317
            mstore(0xa0, m5)
1318
        }
1319
    }
1320

                            
                        
1321
    function log(bool p0, bool p1, address p2) internal pure {
1322
        bytes32 m0;
1323
        bytes32 m1;
1324
        bytes32 m2;
1325
        bytes32 m3;
1326
        /// @solidity memory-safe-assembly
1327
        assembly {
1328
            m0 := mload(0x00)
1329
            m1 := mload(0x20)
1330
            m2 := mload(0x40)
1331
            m3 := mload(0x60)
1332
            // Selector of `log(bool,bool,address)`.
1333
            mstore(0x00, 0x1078f68d)
1334
            mstore(0x20, p0)
1335
            mstore(0x40, p1)
1336
            mstore(0x60, p2)
1337
        }
1338
        _sendLogPayload(0x1c, 0x64);
1339
        /// @solidity memory-safe-assembly
1340
        assembly {
1341
            mstore(0x00, m0)
1342
            mstore(0x20, m1)
1343
            mstore(0x40, m2)
1344
            mstore(0x60, m3)
1345
        }
1346
    }
1347

                            
                        
1348
    function log(bool p0, bool p1, bool p2) internal pure {
1349
        bytes32 m0;
1350
        bytes32 m1;
1351
        bytes32 m2;
1352
        bytes32 m3;
1353
        /// @solidity memory-safe-assembly
1354
        assembly {
1355
            m0 := mload(0x00)
1356
            m1 := mload(0x20)
1357
            m2 := mload(0x40)
1358
            m3 := mload(0x60)
1359
            // Selector of `log(bool,bool,bool)`.
1360
            mstore(0x00, 0x50709698)
1361
            mstore(0x20, p0)
1362
            mstore(0x40, p1)
1363
            mstore(0x60, p2)
1364
        }
1365
        _sendLogPayload(0x1c, 0x64);
1366
        /// @solidity memory-safe-assembly
1367
        assembly {
1368
            mstore(0x00, m0)
1369
            mstore(0x20, m1)
1370
            mstore(0x40, m2)
1371
            mstore(0x60, m3)
1372
        }
1373
    }
1374

                            
                        
1375
    function log(bool p0, bool p1, uint256 p2) internal pure {
1376
        bytes32 m0;
1377
        bytes32 m1;
1378
        bytes32 m2;
1379
        bytes32 m3;
1380
        /// @solidity memory-safe-assembly
1381
        assembly {
1382
            m0 := mload(0x00)
1383
            m1 := mload(0x20)
1384
            m2 := mload(0x40)
1385
            m3 := mload(0x60)
1386
            // Selector of `log(bool,bool,uint256)`.
1387
            mstore(0x00, 0x12f21602)
1388
            mstore(0x20, p0)
1389
            mstore(0x40, p1)
1390
            mstore(0x60, p2)
1391
        }
1392
        _sendLogPayload(0x1c, 0x64);
1393
        /// @solidity memory-safe-assembly
1394
        assembly {
1395
            mstore(0x00, m0)
1396
            mstore(0x20, m1)
1397
            mstore(0x40, m2)
1398
            mstore(0x60, m3)
1399
        }
1400
    }
1401

                            
                        
1402
    function log(bool p0, bool p1, bytes32 p2) internal pure {
1403
        bytes32 m0;
1404
        bytes32 m1;
1405
        bytes32 m2;
1406
        bytes32 m3;
1407
        bytes32 m4;
1408
        bytes32 m5;
1409
        /// @solidity memory-safe-assembly
1410
        assembly {
1411
            function writeString(pos, w) {
1412
                let length := 0
1413
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1414
                mstore(pos, length)
1415
                let shift := sub(256, shl(3, length))
1416
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1417
            }
1418
            m0 := mload(0x00)
1419
            m1 := mload(0x20)
1420
            m2 := mload(0x40)
1421
            m3 := mload(0x60)
1422
            m4 := mload(0x80)
1423
            m5 := mload(0xa0)
1424
            // Selector of `log(bool,bool,string)`.
1425
            mstore(0x00, 0x2555fa46)
1426
            mstore(0x20, p0)
1427
            mstore(0x40, p1)
1428
            mstore(0x60, 0x60)
1429
            writeString(0x80, p2)
1430
        }
1431
        _sendLogPayload(0x1c, 0xa4);
1432
        /// @solidity memory-safe-assembly
1433
        assembly {
1434
            mstore(0x00, m0)
1435
            mstore(0x20, m1)
1436
            mstore(0x40, m2)
1437
            mstore(0x60, m3)
1438
            mstore(0x80, m4)
1439
            mstore(0xa0, m5)
1440
        }
1441
    }
1442

                            
                        
1443
    function log(bool p0, uint256 p1, address p2) internal pure {
1444
        bytes32 m0;
1445
        bytes32 m1;
1446
        bytes32 m2;
1447
        bytes32 m3;
1448
        /// @solidity memory-safe-assembly
1449
        assembly {
1450
            m0 := mload(0x00)
1451
            m1 := mload(0x20)
1452
            m2 := mload(0x40)
1453
            m3 := mload(0x60)
1454
            // Selector of `log(bool,uint256,address)`.
1455
            mstore(0x00, 0x088ef9d2)
1456
            mstore(0x20, p0)
1457
            mstore(0x40, p1)
1458
            mstore(0x60, p2)
1459
        }
1460
        _sendLogPayload(0x1c, 0x64);
1461
        /// @solidity memory-safe-assembly
1462
        assembly {
1463
            mstore(0x00, m0)
1464
            mstore(0x20, m1)
1465
            mstore(0x40, m2)
1466
            mstore(0x60, m3)
1467
        }
1468
    }
1469

                            
                        
1470
    function log(bool p0, uint256 p1, bool p2) internal pure {
1471
        bytes32 m0;
1472
        bytes32 m1;
1473
        bytes32 m2;
1474
        bytes32 m3;
1475
        /// @solidity memory-safe-assembly
1476
        assembly {
1477
            m0 := mload(0x00)
1478
            m1 := mload(0x20)
1479
            m2 := mload(0x40)
1480
            m3 := mload(0x60)
1481
            // Selector of `log(bool,uint256,bool)`.
1482
            mstore(0x00, 0xe8defba9)
1483
            mstore(0x20, p0)
1484
            mstore(0x40, p1)
1485
            mstore(0x60, p2)
1486
        }
1487
        _sendLogPayload(0x1c, 0x64);
1488
        /// @solidity memory-safe-assembly
1489
        assembly {
1490
            mstore(0x00, m0)
1491
            mstore(0x20, m1)
1492
            mstore(0x40, m2)
1493
            mstore(0x60, m3)
1494
        }
1495
    }
1496

                            
                        
1497
    function log(bool p0, uint256 p1, uint256 p2) internal pure {
1498
        bytes32 m0;
1499
        bytes32 m1;
1500
        bytes32 m2;
1501
        bytes32 m3;
1502
        /// @solidity memory-safe-assembly
1503
        assembly {
1504
            m0 := mload(0x00)
1505
            m1 := mload(0x20)
1506
            m2 := mload(0x40)
1507
            m3 := mload(0x60)
1508
            // Selector of `log(bool,uint256,uint256)`.
1509
            mstore(0x00, 0x37103367)
1510
            mstore(0x20, p0)
1511
            mstore(0x40, p1)
1512
            mstore(0x60, p2)
1513
        }
1514
        _sendLogPayload(0x1c, 0x64);
1515
        /// @solidity memory-safe-assembly
1516
        assembly {
1517
            mstore(0x00, m0)
1518
            mstore(0x20, m1)
1519
            mstore(0x40, m2)
1520
            mstore(0x60, m3)
1521
        }
1522
    }
1523

                            
                        
1524
    function log(bool p0, uint256 p1, bytes32 p2) internal pure {
1525
        bytes32 m0;
1526
        bytes32 m1;
1527
        bytes32 m2;
1528
        bytes32 m3;
1529
        bytes32 m4;
1530
        bytes32 m5;
1531
        /// @solidity memory-safe-assembly
1532
        assembly {
1533
            function writeString(pos, w) {
1534
                let length := 0
1535
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1536
                mstore(pos, length)
1537
                let shift := sub(256, shl(3, length))
1538
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1539
            }
1540
            m0 := mload(0x00)
1541
            m1 := mload(0x20)
1542
            m2 := mload(0x40)
1543
            m3 := mload(0x60)
1544
            m4 := mload(0x80)
1545
            m5 := mload(0xa0)
1546
            // Selector of `log(bool,uint256,string)`.
1547
            mstore(0x00, 0xc3fc3970)
1548
            mstore(0x20, p0)
1549
            mstore(0x40, p1)
1550
            mstore(0x60, 0x60)
1551
            writeString(0x80, p2)
1552
        }
1553
        _sendLogPayload(0x1c, 0xa4);
1554
        /// @solidity memory-safe-assembly
1555
        assembly {
1556
            mstore(0x00, m0)
1557
            mstore(0x20, m1)
1558
            mstore(0x40, m2)
1559
            mstore(0x60, m3)
1560
            mstore(0x80, m4)
1561
            mstore(0xa0, m5)
1562
        }
1563
    }
1564

                            
                        
1565
    function log(bool p0, bytes32 p1, address p2) internal pure {
1566
        bytes32 m0;
1567
        bytes32 m1;
1568
        bytes32 m2;
1569
        bytes32 m3;
1570
        bytes32 m4;
1571
        bytes32 m5;
1572
        /// @solidity memory-safe-assembly
1573
        assembly {
1574
            function writeString(pos, w) {
1575
                let length := 0
1576
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1577
                mstore(pos, length)
1578
                let shift := sub(256, shl(3, length))
1579
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1580
            }
1581
            m0 := mload(0x00)
1582
            m1 := mload(0x20)
1583
            m2 := mload(0x40)
1584
            m3 := mload(0x60)
1585
            m4 := mload(0x80)
1586
            m5 := mload(0xa0)
1587
            // Selector of `log(bool,string,address)`.
1588
            mstore(0x00, 0x9591b953)
1589
            mstore(0x20, p0)
1590
            mstore(0x40, 0x60)
1591
            mstore(0x60, p2)
1592
            writeString(0x80, p1)
1593
        }
1594
        _sendLogPayload(0x1c, 0xa4);
1595
        /// @solidity memory-safe-assembly
1596
        assembly {
1597
            mstore(0x00, m0)
1598
            mstore(0x20, m1)
1599
            mstore(0x40, m2)
1600
            mstore(0x60, m3)
1601
            mstore(0x80, m4)
1602
            mstore(0xa0, m5)
1603
        }
1604
    }
1605

                            
                        
1606
    function log(bool p0, bytes32 p1, bool p2) internal pure {
1607
        bytes32 m0;
1608
        bytes32 m1;
1609
        bytes32 m2;
1610
        bytes32 m3;
1611
        bytes32 m4;
1612
        bytes32 m5;
1613
        /// @solidity memory-safe-assembly
1614
        assembly {
1615
            function writeString(pos, w) {
1616
                let length := 0
1617
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1618
                mstore(pos, length)
1619
                let shift := sub(256, shl(3, length))
1620
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1621
            }
1622
            m0 := mload(0x00)
1623
            m1 := mload(0x20)
1624
            m2 := mload(0x40)
1625
            m3 := mload(0x60)
1626
            m4 := mload(0x80)
1627
            m5 := mload(0xa0)
1628
            // Selector of `log(bool,string,bool)`.
1629
            mstore(0x00, 0xdbb4c247)
1630
            mstore(0x20, p0)
1631
            mstore(0x40, 0x60)
1632
            mstore(0x60, p2)
1633
            writeString(0x80, p1)
1634
        }
1635
        _sendLogPayload(0x1c, 0xa4);
1636
        /// @solidity memory-safe-assembly
1637
        assembly {
1638
            mstore(0x00, m0)
1639
            mstore(0x20, m1)
1640
            mstore(0x40, m2)
1641
            mstore(0x60, m3)
1642
            mstore(0x80, m4)
1643
            mstore(0xa0, m5)
1644
        }
1645
    }
1646

                            
                        
1647
    function log(bool p0, bytes32 p1, uint256 p2) internal pure {
1648
        bytes32 m0;
1649
        bytes32 m1;
1650
        bytes32 m2;
1651
        bytes32 m3;
1652
        bytes32 m4;
1653
        bytes32 m5;
1654
        /// @solidity memory-safe-assembly
1655
        assembly {
1656
            function writeString(pos, w) {
1657
                let length := 0
1658
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1659
                mstore(pos, length)
1660
                let shift := sub(256, shl(3, length))
1661
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1662
            }
1663
            m0 := mload(0x00)
1664
            m1 := mload(0x20)
1665
            m2 := mload(0x40)
1666
            m3 := mload(0x60)
1667
            m4 := mload(0x80)
1668
            m5 := mload(0xa0)
1669
            // Selector of `log(bool,string,uint256)`.
1670
            mstore(0x00, 0x1093ee11)
1671
            mstore(0x20, p0)
1672
            mstore(0x40, 0x60)
1673
            mstore(0x60, p2)
1674
            writeString(0x80, p1)
1675
        }
1676
        _sendLogPayload(0x1c, 0xa4);
1677
        /// @solidity memory-safe-assembly
1678
        assembly {
1679
            mstore(0x00, m0)
1680
            mstore(0x20, m1)
1681
            mstore(0x40, m2)
1682
            mstore(0x60, m3)
1683
            mstore(0x80, m4)
1684
            mstore(0xa0, m5)
1685
        }
1686
    }
1687

                            
                        
1688
    function log(bool p0, bytes32 p1, bytes32 p2) internal pure {
1689
        bytes32 m0;
1690
        bytes32 m1;
1691
        bytes32 m2;
1692
        bytes32 m3;
1693
        bytes32 m4;
1694
        bytes32 m5;
1695
        bytes32 m6;
1696
        bytes32 m7;
1697
        /// @solidity memory-safe-assembly
1698
        assembly {
1699
            function writeString(pos, w) {
1700
                let length := 0
1701
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1702
                mstore(pos, length)
1703
                let shift := sub(256, shl(3, length))
1704
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1705
            }
1706
            m0 := mload(0x00)
1707
            m1 := mload(0x20)
1708
            m2 := mload(0x40)
1709
            m3 := mload(0x60)
1710
            m4 := mload(0x80)
1711
            m5 := mload(0xa0)
1712
            m6 := mload(0xc0)
1713
            m7 := mload(0xe0)
1714
            // Selector of `log(bool,string,string)`.
1715
            mstore(0x00, 0xb076847f)
1716
            mstore(0x20, p0)
1717
            mstore(0x40, 0x60)
1718
            mstore(0x60, 0xa0)
1719
            writeString(0x80, p1)
1720
            writeString(0xc0, p2)
1721
        }
1722
        _sendLogPayload(0x1c, 0xe4);
1723
        /// @solidity memory-safe-assembly
1724
        assembly {
1725
            mstore(0x00, m0)
1726
            mstore(0x20, m1)
1727
            mstore(0x40, m2)
1728
            mstore(0x60, m3)
1729
            mstore(0x80, m4)
1730
            mstore(0xa0, m5)
1731
            mstore(0xc0, m6)
1732
            mstore(0xe0, m7)
1733
        }
1734
    }
1735

                            
                        
1736
    function log(uint256 p0, address p1, address p2) internal pure {
1737
        bytes32 m0;
1738
        bytes32 m1;
1739
        bytes32 m2;
1740
        bytes32 m3;
1741
        /// @solidity memory-safe-assembly
1742
        assembly {
1743
            m0 := mload(0x00)
1744
            m1 := mload(0x20)
1745
            m2 := mload(0x40)
1746
            m3 := mload(0x60)
1747
            // Selector of `log(uint256,address,address)`.
1748
            mstore(0x00, 0xbcfd9be0)
1749
            mstore(0x20, p0)
1750
            mstore(0x40, p1)
1751
            mstore(0x60, p2)
1752
        }
1753
        _sendLogPayload(0x1c, 0x64);
1754
        /// @solidity memory-safe-assembly
1755
        assembly {
1756
            mstore(0x00, m0)
1757
            mstore(0x20, m1)
1758
            mstore(0x40, m2)
1759
            mstore(0x60, m3)
1760
        }
1761
    }
1762

                            
                        
1763
    function log(uint256 p0, address p1, bool p2) internal pure {
1764
        bytes32 m0;
1765
        bytes32 m1;
1766
        bytes32 m2;
1767
        bytes32 m3;
1768
        /// @solidity memory-safe-assembly
1769
        assembly {
1770
            m0 := mload(0x00)
1771
            m1 := mload(0x20)
1772
            m2 := mload(0x40)
1773
            m3 := mload(0x60)
1774
            // Selector of `log(uint256,address,bool)`.
1775
            mstore(0x00, 0x9b6ec042)
1776
            mstore(0x20, p0)
1777
            mstore(0x40, p1)
1778
            mstore(0x60, p2)
1779
        }
1780
        _sendLogPayload(0x1c, 0x64);
1781
        /// @solidity memory-safe-assembly
1782
        assembly {
1783
            mstore(0x00, m0)
1784
            mstore(0x20, m1)
1785
            mstore(0x40, m2)
1786
            mstore(0x60, m3)
1787
        }
1788
    }
1789

                            
                        
1790
    function log(uint256 p0, address p1, uint256 p2) internal pure {
1791
        bytes32 m0;
1792
        bytes32 m1;
1793
        bytes32 m2;
1794
        bytes32 m3;
1795
        /// @solidity memory-safe-assembly
1796
        assembly {
1797
            m0 := mload(0x00)
1798
            m1 := mload(0x20)
1799
            m2 := mload(0x40)
1800
            m3 := mload(0x60)
1801
            // Selector of `log(uint256,address,uint256)`.
1802
            mstore(0x00, 0x5a9b5ed5)
1803
            mstore(0x20, p0)
1804
            mstore(0x40, p1)
1805
            mstore(0x60, p2)
1806
        }
1807
        _sendLogPayload(0x1c, 0x64);
1808
        /// @solidity memory-safe-assembly
1809
        assembly {
1810
            mstore(0x00, m0)
1811
            mstore(0x20, m1)
1812
            mstore(0x40, m2)
1813
            mstore(0x60, m3)
1814
        }
1815
    }
1816

                            
                        
1817
    function log(uint256 p0, address p1, bytes32 p2) internal pure {
1818
        bytes32 m0;
1819
        bytes32 m1;
1820
        bytes32 m2;
1821
        bytes32 m3;
1822
        bytes32 m4;
1823
        bytes32 m5;
1824
        /// @solidity memory-safe-assembly
1825
        assembly {
1826
            function writeString(pos, w) {
1827
                let length := 0
1828
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1829
                mstore(pos, length)
1830
                let shift := sub(256, shl(3, length))
1831
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1832
            }
1833
            m0 := mload(0x00)
1834
            m1 := mload(0x20)
1835
            m2 := mload(0x40)
1836
            m3 := mload(0x60)
1837
            m4 := mload(0x80)
1838
            m5 := mload(0xa0)
1839
            // Selector of `log(uint256,address,string)`.
1840
            mstore(0x00, 0x63cb41f9)
1841
            mstore(0x20, p0)
1842
            mstore(0x40, p1)
1843
            mstore(0x60, 0x60)
1844
            writeString(0x80, p2)
1845
        }
1846
        _sendLogPayload(0x1c, 0xa4);
1847
        /// @solidity memory-safe-assembly
1848
        assembly {
1849
            mstore(0x00, m0)
1850
            mstore(0x20, m1)
1851
            mstore(0x40, m2)
1852
            mstore(0x60, m3)
1853
            mstore(0x80, m4)
1854
            mstore(0xa0, m5)
1855
        }
1856
    }
1857

                            
                        
1858
    function log(uint256 p0, bool p1, address p2) internal pure {
1859
        bytes32 m0;
1860
        bytes32 m1;
1861
        bytes32 m2;
1862
        bytes32 m3;
1863
        /// @solidity memory-safe-assembly
1864
        assembly {
1865
            m0 := mload(0x00)
1866
            m1 := mload(0x20)
1867
            m2 := mload(0x40)
1868
            m3 := mload(0x60)
1869
            // Selector of `log(uint256,bool,address)`.
1870
            mstore(0x00, 0x35085f7b)
1871
            mstore(0x20, p0)
1872
            mstore(0x40, p1)
1873
            mstore(0x60, p2)
1874
        }
1875
        _sendLogPayload(0x1c, 0x64);
1876
        /// @solidity memory-safe-assembly
1877
        assembly {
1878
            mstore(0x00, m0)
1879
            mstore(0x20, m1)
1880
            mstore(0x40, m2)
1881
            mstore(0x60, m3)
1882
        }
1883
    }
1884

                            
                        
1885
    function log(uint256 p0, bool p1, bool p2) internal pure {
1886
        bytes32 m0;
1887
        bytes32 m1;
1888
        bytes32 m2;
1889
        bytes32 m3;
1890
        /// @solidity memory-safe-assembly
1891
        assembly {
1892
            m0 := mload(0x00)
1893
            m1 := mload(0x20)
1894
            m2 := mload(0x40)
1895
            m3 := mload(0x60)
1896
            // Selector of `log(uint256,bool,bool)`.
1897
            mstore(0x00, 0x20718650)
1898
            mstore(0x20, p0)
1899
            mstore(0x40, p1)
1900
            mstore(0x60, p2)
1901
        }
1902
        _sendLogPayload(0x1c, 0x64);
1903
        /// @solidity memory-safe-assembly
1904
        assembly {
1905
            mstore(0x00, m0)
1906
            mstore(0x20, m1)
1907
            mstore(0x40, m2)
1908
            mstore(0x60, m3)
1909
        }
1910
    }
1911

                            
                        
1912
    function log(uint256 p0, bool p1, uint256 p2) internal pure {
1913
        bytes32 m0;
1914
        bytes32 m1;
1915
        bytes32 m2;
1916
        bytes32 m3;
1917
        /// @solidity memory-safe-assembly
1918
        assembly {
1919
            m0 := mload(0x00)
1920
            m1 := mload(0x20)
1921
            m2 := mload(0x40)
1922
            m3 := mload(0x60)
1923
            // Selector of `log(uint256,bool,uint256)`.
1924
            mstore(0x00, 0x20098014)
1925
            mstore(0x20, p0)
1926
            mstore(0x40, p1)
1927
            mstore(0x60, p2)
1928
        }
1929
        _sendLogPayload(0x1c, 0x64);
1930
        /// @solidity memory-safe-assembly
1931
        assembly {
1932
            mstore(0x00, m0)
1933
            mstore(0x20, m1)
1934
            mstore(0x40, m2)
1935
            mstore(0x60, m3)
1936
        }
1937
    }
1938

                            
                        
1939
    function log(uint256 p0, bool p1, bytes32 p2) internal pure {
1940
        bytes32 m0;
1941
        bytes32 m1;
1942
        bytes32 m2;
1943
        bytes32 m3;
1944
        bytes32 m4;
1945
        bytes32 m5;
1946
        /// @solidity memory-safe-assembly
1947
        assembly {
1948
            function writeString(pos, w) {
1949
                let length := 0
1950
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
1951
                mstore(pos, length)
1952
                let shift := sub(256, shl(3, length))
1953
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
1954
            }
1955
            m0 := mload(0x00)
1956
            m1 := mload(0x20)
1957
            m2 := mload(0x40)
1958
            m3 := mload(0x60)
1959
            m4 := mload(0x80)
1960
            m5 := mload(0xa0)
1961
            // Selector of `log(uint256,bool,string)`.
1962
            mstore(0x00, 0x85775021)
1963
            mstore(0x20, p0)
1964
            mstore(0x40, p1)
1965
            mstore(0x60, 0x60)
1966
            writeString(0x80, p2)
1967
        }
1968
        _sendLogPayload(0x1c, 0xa4);
1969
        /// @solidity memory-safe-assembly
1970
        assembly {
1971
            mstore(0x00, m0)
1972
            mstore(0x20, m1)
1973
            mstore(0x40, m2)
1974
            mstore(0x60, m3)
1975
            mstore(0x80, m4)
1976
            mstore(0xa0, m5)
1977
        }
1978
    }
1979

                            
                        
1980
    function log(uint256 p0, uint256 p1, address p2) internal pure {
1981
        bytes32 m0;
1982
        bytes32 m1;
1983
        bytes32 m2;
1984
        bytes32 m3;
1985
        /// @solidity memory-safe-assembly
1986
        assembly {
1987
            m0 := mload(0x00)
1988
            m1 := mload(0x20)
1989
            m2 := mload(0x40)
1990
            m3 := mload(0x60)
1991
            // Selector of `log(uint256,uint256,address)`.
1992
            mstore(0x00, 0x5c96b331)
1993
            mstore(0x20, p0)
1994
            mstore(0x40, p1)
1995
            mstore(0x60, p2)
1996
        }
1997
        _sendLogPayload(0x1c, 0x64);
1998
        /// @solidity memory-safe-assembly
1999
        assembly {
2000
            mstore(0x00, m0)
2001
            mstore(0x20, m1)
2002
            mstore(0x40, m2)
2003
            mstore(0x60, m3)
2004
        }
2005
    }
2006

                            
                        
2007
    function log(uint256 p0, uint256 p1, bool p2) internal pure {
2008
        bytes32 m0;
2009
        bytes32 m1;
2010
        bytes32 m2;
2011
        bytes32 m3;
2012
        /// @solidity memory-safe-assembly
2013
        assembly {
2014
            m0 := mload(0x00)
2015
            m1 := mload(0x20)
2016
            m2 := mload(0x40)
2017
            m3 := mload(0x60)
2018
            // Selector of `log(uint256,uint256,bool)`.
2019
            mstore(0x00, 0x4766da72)
2020
            mstore(0x20, p0)
2021
            mstore(0x40, p1)
2022
            mstore(0x60, p2)
2023
        }
2024
        _sendLogPayload(0x1c, 0x64);
2025
        /// @solidity memory-safe-assembly
2026
        assembly {
2027
            mstore(0x00, m0)
2028
            mstore(0x20, m1)
2029
            mstore(0x40, m2)
2030
            mstore(0x60, m3)
2031
        }
2032
    }
2033

                            
                        
2034
    function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
2035
        bytes32 m0;
2036
        bytes32 m1;
2037
        bytes32 m2;
2038
        bytes32 m3;
2039
        /// @solidity memory-safe-assembly
2040
        assembly {
2041
            m0 := mload(0x00)
2042
            m1 := mload(0x20)
2043
            m2 := mload(0x40)
2044
            m3 := mload(0x60)
2045
            // Selector of `log(uint256,uint256,uint256)`.
2046
            mstore(0x00, 0xd1ed7a3c)
2047
            mstore(0x20, p0)
2048
            mstore(0x40, p1)
2049
            mstore(0x60, p2)
2050
        }
2051
        _sendLogPayload(0x1c, 0x64);
2052
        /// @solidity memory-safe-assembly
2053
        assembly {
2054
            mstore(0x00, m0)
2055
            mstore(0x20, m1)
2056
            mstore(0x40, m2)
2057
            mstore(0x60, m3)
2058
        }
2059
    }
2060

                            
                        
2061
    function log(uint256 p0, uint256 p1, bytes32 p2) internal pure {
2062
        bytes32 m0;
2063
        bytes32 m1;
2064
        bytes32 m2;
2065
        bytes32 m3;
2066
        bytes32 m4;
2067
        bytes32 m5;
2068
        /// @solidity memory-safe-assembly
2069
        assembly {
2070
            function writeString(pos, w) {
2071
                let length := 0
2072
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2073
                mstore(pos, length)
2074
                let shift := sub(256, shl(3, length))
2075
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2076
            }
2077
            m0 := mload(0x00)
2078
            m1 := mload(0x20)
2079
            m2 := mload(0x40)
2080
            m3 := mload(0x60)
2081
            m4 := mload(0x80)
2082
            m5 := mload(0xa0)
2083
            // Selector of `log(uint256,uint256,string)`.
2084
            mstore(0x00, 0x71d04af2)
2085
            mstore(0x20, p0)
2086
            mstore(0x40, p1)
2087
            mstore(0x60, 0x60)
2088
            writeString(0x80, p2)
2089
        }
2090
        _sendLogPayload(0x1c, 0xa4);
2091
        /// @solidity memory-safe-assembly
2092
        assembly {
2093
            mstore(0x00, m0)
2094
            mstore(0x20, m1)
2095
            mstore(0x40, m2)
2096
            mstore(0x60, m3)
2097
            mstore(0x80, m4)
2098
            mstore(0xa0, m5)
2099
        }
2100
    }
2101

                            
                        
2102
    function log(uint256 p0, bytes32 p1, address p2) internal pure {
2103
        bytes32 m0;
2104
        bytes32 m1;
2105
        bytes32 m2;
2106
        bytes32 m3;
2107
        bytes32 m4;
2108
        bytes32 m5;
2109
        /// @solidity memory-safe-assembly
2110
        assembly {
2111
            function writeString(pos, w) {
2112
                let length := 0
2113
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2114
                mstore(pos, length)
2115
                let shift := sub(256, shl(3, length))
2116
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2117
            }
2118
            m0 := mload(0x00)
2119
            m1 := mload(0x20)
2120
            m2 := mload(0x40)
2121
            m3 := mload(0x60)
2122
            m4 := mload(0x80)
2123
            m5 := mload(0xa0)
2124
            // Selector of `log(uint256,string,address)`.
2125
            mstore(0x00, 0x7afac959)
2126
            mstore(0x20, p0)
2127
            mstore(0x40, 0x60)
2128
            mstore(0x60, p2)
2129
            writeString(0x80, p1)
2130
        }
2131
        _sendLogPayload(0x1c, 0xa4);
2132
        /// @solidity memory-safe-assembly
2133
        assembly {
2134
            mstore(0x00, m0)
2135
            mstore(0x20, m1)
2136
            mstore(0x40, m2)
2137
            mstore(0x60, m3)
2138
            mstore(0x80, m4)
2139
            mstore(0xa0, m5)
2140
        }
2141
    }
2142

                            
                        
2143
    function log(uint256 p0, bytes32 p1, bool p2) internal pure {
2144
        bytes32 m0;
2145
        bytes32 m1;
2146
        bytes32 m2;
2147
        bytes32 m3;
2148
        bytes32 m4;
2149
        bytes32 m5;
2150
        /// @solidity memory-safe-assembly
2151
        assembly {
2152
            function writeString(pos, w) {
2153
                let length := 0
2154
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2155
                mstore(pos, length)
2156
                let shift := sub(256, shl(3, length))
2157
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2158
            }
2159
            m0 := mload(0x00)
2160
            m1 := mload(0x20)
2161
            m2 := mload(0x40)
2162
            m3 := mload(0x60)
2163
            m4 := mload(0x80)
2164
            m5 := mload(0xa0)
2165
            // Selector of `log(uint256,string,bool)`.
2166
            mstore(0x00, 0x4ceda75a)
2167
            mstore(0x20, p0)
2168
            mstore(0x40, 0x60)
2169
            mstore(0x60, p2)
2170
            writeString(0x80, p1)
2171
        }
2172
        _sendLogPayload(0x1c, 0xa4);
2173
        /// @solidity memory-safe-assembly
2174
        assembly {
2175
            mstore(0x00, m0)
2176
            mstore(0x20, m1)
2177
            mstore(0x40, m2)
2178
            mstore(0x60, m3)
2179
            mstore(0x80, m4)
2180
            mstore(0xa0, m5)
2181
        }
2182
    }
2183

                            
                        
2184
    function log(uint256 p0, bytes32 p1, uint256 p2) internal pure {
2185
        bytes32 m0;
2186
        bytes32 m1;
2187
        bytes32 m2;
2188
        bytes32 m3;
2189
        bytes32 m4;
2190
        bytes32 m5;
2191
        /// @solidity memory-safe-assembly
2192
        assembly {
2193
            function writeString(pos, w) {
2194
                let length := 0
2195
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2196
                mstore(pos, length)
2197
                let shift := sub(256, shl(3, length))
2198
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2199
            }
2200
            m0 := mload(0x00)
2201
            m1 := mload(0x20)
2202
            m2 := mload(0x40)
2203
            m3 := mload(0x60)
2204
            m4 := mload(0x80)
2205
            m5 := mload(0xa0)
2206
            // Selector of `log(uint256,string,uint256)`.
2207
            mstore(0x00, 0x37aa7d4c)
2208
            mstore(0x20, p0)
2209
            mstore(0x40, 0x60)
2210
            mstore(0x60, p2)
2211
            writeString(0x80, p1)
2212
        }
2213
        _sendLogPayload(0x1c, 0xa4);
2214
        /// @solidity memory-safe-assembly
2215
        assembly {
2216
            mstore(0x00, m0)
2217
            mstore(0x20, m1)
2218
            mstore(0x40, m2)
2219
            mstore(0x60, m3)
2220
            mstore(0x80, m4)
2221
            mstore(0xa0, m5)
2222
        }
2223
    }
2224

                            
                        
2225
    function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure {
2226
        bytes32 m0;
2227
        bytes32 m1;
2228
        bytes32 m2;
2229
        bytes32 m3;
2230
        bytes32 m4;
2231
        bytes32 m5;
2232
        bytes32 m6;
2233
        bytes32 m7;
2234
        /// @solidity memory-safe-assembly
2235
        assembly {
2236
            function writeString(pos, w) {
2237
                let length := 0
2238
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2239
                mstore(pos, length)
2240
                let shift := sub(256, shl(3, length))
2241
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2242
            }
2243
            m0 := mload(0x00)
2244
            m1 := mload(0x20)
2245
            m2 := mload(0x40)
2246
            m3 := mload(0x60)
2247
            m4 := mload(0x80)
2248
            m5 := mload(0xa0)
2249
            m6 := mload(0xc0)
2250
            m7 := mload(0xe0)
2251
            // Selector of `log(uint256,string,string)`.
2252
            mstore(0x00, 0xb115611f)
2253
            mstore(0x20, p0)
2254
            mstore(0x40, 0x60)
2255
            mstore(0x60, 0xa0)
2256
            writeString(0x80, p1)
2257
            writeString(0xc0, p2)
2258
        }
2259
        _sendLogPayload(0x1c, 0xe4);
2260
        /// @solidity memory-safe-assembly
2261
        assembly {
2262
            mstore(0x00, m0)
2263
            mstore(0x20, m1)
2264
            mstore(0x40, m2)
2265
            mstore(0x60, m3)
2266
            mstore(0x80, m4)
2267
            mstore(0xa0, m5)
2268
            mstore(0xc0, m6)
2269
            mstore(0xe0, m7)
2270
        }
2271
    }
2272

                            
                        
2273
    function log(bytes32 p0, address p1, address p2) internal pure {
2274
        bytes32 m0;
2275
        bytes32 m1;
2276
        bytes32 m2;
2277
        bytes32 m3;
2278
        bytes32 m4;
2279
        bytes32 m5;
2280
        /// @solidity memory-safe-assembly
2281
        assembly {
2282
            function writeString(pos, w) {
2283
                let length := 0
2284
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2285
                mstore(pos, length)
2286
                let shift := sub(256, shl(3, length))
2287
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2288
            }
2289
            m0 := mload(0x00)
2290
            m1 := mload(0x20)
2291
            m2 := mload(0x40)
2292
            m3 := mload(0x60)
2293
            m4 := mload(0x80)
2294
            m5 := mload(0xa0)
2295
            // Selector of `log(string,address,address)`.
2296
            mstore(0x00, 0xfcec75e0)
2297
            mstore(0x20, 0x60)
2298
            mstore(0x40, p1)
2299
            mstore(0x60, p2)
2300
            writeString(0x80, p0)
2301
        }
2302
        _sendLogPayload(0x1c, 0xa4);
2303
        /// @solidity memory-safe-assembly
2304
        assembly {
2305
            mstore(0x00, m0)
2306
            mstore(0x20, m1)
2307
            mstore(0x40, m2)
2308
            mstore(0x60, m3)
2309
            mstore(0x80, m4)
2310
            mstore(0xa0, m5)
2311
        }
2312
    }
2313

                            
                        
2314
    function log(bytes32 p0, address p1, bool p2) internal pure {
2315
        bytes32 m0;
2316
        bytes32 m1;
2317
        bytes32 m2;
2318
        bytes32 m3;
2319
        bytes32 m4;
2320
        bytes32 m5;
2321
        /// @solidity memory-safe-assembly
2322
        assembly {
2323
            function writeString(pos, w) {
2324
                let length := 0
2325
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2326
                mstore(pos, length)
2327
                let shift := sub(256, shl(3, length))
2328
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2329
            }
2330
            m0 := mload(0x00)
2331
            m1 := mload(0x20)
2332
            m2 := mload(0x40)
2333
            m3 := mload(0x60)
2334
            m4 := mload(0x80)
2335
            m5 := mload(0xa0)
2336
            // Selector of `log(string,address,bool)`.
2337
            mstore(0x00, 0xc91d5ed4)
2338
            mstore(0x20, 0x60)
2339
            mstore(0x40, p1)
2340
            mstore(0x60, p2)
2341
            writeString(0x80, p0)
2342
        }
2343
        _sendLogPayload(0x1c, 0xa4);
2344
        /// @solidity memory-safe-assembly
2345
        assembly {
2346
            mstore(0x00, m0)
2347
            mstore(0x20, m1)
2348
            mstore(0x40, m2)
2349
            mstore(0x60, m3)
2350
            mstore(0x80, m4)
2351
            mstore(0xa0, m5)
2352
        }
2353
    }
2354

                            
                        
2355
    function log(bytes32 p0, address p1, uint256 p2) internal pure {
2356
        bytes32 m0;
2357
        bytes32 m1;
2358
        bytes32 m2;
2359
        bytes32 m3;
2360
        bytes32 m4;
2361
        bytes32 m5;
2362
        /// @solidity memory-safe-assembly
2363
        assembly {
2364
            function writeString(pos, w) {
2365
                let length := 0
2366
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2367
                mstore(pos, length)
2368
                let shift := sub(256, shl(3, length))
2369
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2370
            }
2371
            m0 := mload(0x00)
2372
            m1 := mload(0x20)
2373
            m2 := mload(0x40)
2374
            m3 := mload(0x60)
2375
            m4 := mload(0x80)
2376
            m5 := mload(0xa0)
2377
            // Selector of `log(string,address,uint256)`.
2378
            mstore(0x00, 0x0d26b925)
2379
            mstore(0x20, 0x60)
2380
            mstore(0x40, p1)
2381
            mstore(0x60, p2)
2382
            writeString(0x80, p0)
2383
        }
2384
        _sendLogPayload(0x1c, 0xa4);
2385
        /// @solidity memory-safe-assembly
2386
        assembly {
2387
            mstore(0x00, m0)
2388
            mstore(0x20, m1)
2389
            mstore(0x40, m2)
2390
            mstore(0x60, m3)
2391
            mstore(0x80, m4)
2392
            mstore(0xa0, m5)
2393
        }
2394
    }
2395

                            
                        
2396
    function log(bytes32 p0, address p1, bytes32 p2) internal pure {
2397
        bytes32 m0;
2398
        bytes32 m1;
2399
        bytes32 m2;
2400
        bytes32 m3;
2401
        bytes32 m4;
2402
        bytes32 m5;
2403
        bytes32 m6;
2404
        bytes32 m7;
2405
        /// @solidity memory-safe-assembly
2406
        assembly {
2407
            function writeString(pos, w) {
2408
                let length := 0
2409
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2410
                mstore(pos, length)
2411
                let shift := sub(256, shl(3, length))
2412
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2413
            }
2414
            m0 := mload(0x00)
2415
            m1 := mload(0x20)
2416
            m2 := mload(0x40)
2417
            m3 := mload(0x60)
2418
            m4 := mload(0x80)
2419
            m5 := mload(0xa0)
2420
            m6 := mload(0xc0)
2421
            m7 := mload(0xe0)
2422
            // Selector of `log(string,address,string)`.
2423
            mstore(0x00, 0xe0e9ad4f)
2424
            mstore(0x20, 0x60)
2425
            mstore(0x40, p1)
2426
            mstore(0x60, 0xa0)
2427
            writeString(0x80, p0)
2428
            writeString(0xc0, p2)
2429
        }
2430
        _sendLogPayload(0x1c, 0xe4);
2431
        /// @solidity memory-safe-assembly
2432
        assembly {
2433
            mstore(0x00, m0)
2434
            mstore(0x20, m1)
2435
            mstore(0x40, m2)
2436
            mstore(0x60, m3)
2437
            mstore(0x80, m4)
2438
            mstore(0xa0, m5)
2439
            mstore(0xc0, m6)
2440
            mstore(0xe0, m7)
2441
        }
2442
    }
2443

                            
                        
2444
    function log(bytes32 p0, bool p1, address p2) internal pure {
2445
        bytes32 m0;
2446
        bytes32 m1;
2447
        bytes32 m2;
2448
        bytes32 m3;
2449
        bytes32 m4;
2450
        bytes32 m5;
2451
        /// @solidity memory-safe-assembly
2452
        assembly {
2453
            function writeString(pos, w) {
2454
                let length := 0
2455
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2456
                mstore(pos, length)
2457
                let shift := sub(256, shl(3, length))
2458
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2459
            }
2460
            m0 := mload(0x00)
2461
            m1 := mload(0x20)
2462
            m2 := mload(0x40)
2463
            m3 := mload(0x60)
2464
            m4 := mload(0x80)
2465
            m5 := mload(0xa0)
2466
            // Selector of `log(string,bool,address)`.
2467
            mstore(0x00, 0x932bbb38)
2468
            mstore(0x20, 0x60)
2469
            mstore(0x40, p1)
2470
            mstore(0x60, p2)
2471
            writeString(0x80, p0)
2472
        }
2473
        _sendLogPayload(0x1c, 0xa4);
2474
        /// @solidity memory-safe-assembly
2475
        assembly {
2476
            mstore(0x00, m0)
2477
            mstore(0x20, m1)
2478
            mstore(0x40, m2)
2479
            mstore(0x60, m3)
2480
            mstore(0x80, m4)
2481
            mstore(0xa0, m5)
2482
        }
2483
    }
2484

                            
                        
2485
    function log(bytes32 p0, bool p1, bool p2) internal pure {
2486
        bytes32 m0;
2487
        bytes32 m1;
2488
        bytes32 m2;
2489
        bytes32 m3;
2490
        bytes32 m4;
2491
        bytes32 m5;
2492
        /// @solidity memory-safe-assembly
2493
        assembly {
2494
            function writeString(pos, w) {
2495
                let length := 0
2496
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2497
                mstore(pos, length)
2498
                let shift := sub(256, shl(3, length))
2499
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2500
            }
2501
            m0 := mload(0x00)
2502
            m1 := mload(0x20)
2503
            m2 := mload(0x40)
2504
            m3 := mload(0x60)
2505
            m4 := mload(0x80)
2506
            m5 := mload(0xa0)
2507
            // Selector of `log(string,bool,bool)`.
2508
            mstore(0x00, 0x850b7ad6)
2509
            mstore(0x20, 0x60)
2510
            mstore(0x40, p1)
2511
            mstore(0x60, p2)
2512
            writeString(0x80, p0)
2513
        }
2514
        _sendLogPayload(0x1c, 0xa4);
2515
        /// @solidity memory-safe-assembly
2516
        assembly {
2517
            mstore(0x00, m0)
2518
            mstore(0x20, m1)
2519
            mstore(0x40, m2)
2520
            mstore(0x60, m3)
2521
            mstore(0x80, m4)
2522
            mstore(0xa0, m5)
2523
        }
2524
    }
2525

                            
                        
2526
    function log(bytes32 p0, bool p1, uint256 p2) internal pure {
2527
        bytes32 m0;
2528
        bytes32 m1;
2529
        bytes32 m2;
2530
        bytes32 m3;
2531
        bytes32 m4;
2532
        bytes32 m5;
2533
        /// @solidity memory-safe-assembly
2534
        assembly {
2535
            function writeString(pos, w) {
2536
                let length := 0
2537
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2538
                mstore(pos, length)
2539
                let shift := sub(256, shl(3, length))
2540
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2541
            }
2542
            m0 := mload(0x00)
2543
            m1 := mload(0x20)
2544
            m2 := mload(0x40)
2545
            m3 := mload(0x60)
2546
            m4 := mload(0x80)
2547
            m5 := mload(0xa0)
2548
            // Selector of `log(string,bool,uint256)`.
2549
            mstore(0x00, 0xc95958d6)
2550
            mstore(0x20, 0x60)
2551
            mstore(0x40, p1)
2552
            mstore(0x60, p2)
2553
            writeString(0x80, p0)
2554
        }
2555
        _sendLogPayload(0x1c, 0xa4);
2556
        /// @solidity memory-safe-assembly
2557
        assembly {
2558
            mstore(0x00, m0)
2559
            mstore(0x20, m1)
2560
            mstore(0x40, m2)
2561
            mstore(0x60, m3)
2562
            mstore(0x80, m4)
2563
            mstore(0xa0, m5)
2564
        }
2565
    }
2566

                            
                        
2567
    function log(bytes32 p0, bool p1, bytes32 p2) internal pure {
2568
        bytes32 m0;
2569
        bytes32 m1;
2570
        bytes32 m2;
2571
        bytes32 m3;
2572
        bytes32 m4;
2573
        bytes32 m5;
2574
        bytes32 m6;
2575
        bytes32 m7;
2576
        /// @solidity memory-safe-assembly
2577
        assembly {
2578
            function writeString(pos, w) {
2579
                let length := 0
2580
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2581
                mstore(pos, length)
2582
                let shift := sub(256, shl(3, length))
2583
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2584
            }
2585
            m0 := mload(0x00)
2586
            m1 := mload(0x20)
2587
            m2 := mload(0x40)
2588
            m3 := mload(0x60)
2589
            m4 := mload(0x80)
2590
            m5 := mload(0xa0)
2591
            m6 := mload(0xc0)
2592
            m7 := mload(0xe0)
2593
            // Selector of `log(string,bool,string)`.
2594
            mstore(0x00, 0xe298f47d)
2595
            mstore(0x20, 0x60)
2596
            mstore(0x40, p1)
2597
            mstore(0x60, 0xa0)
2598
            writeString(0x80, p0)
2599
            writeString(0xc0, p2)
2600
        }
2601
        _sendLogPayload(0x1c, 0xe4);
2602
        /// @solidity memory-safe-assembly
2603
        assembly {
2604
            mstore(0x00, m0)
2605
            mstore(0x20, m1)
2606
            mstore(0x40, m2)
2607
            mstore(0x60, m3)
2608
            mstore(0x80, m4)
2609
            mstore(0xa0, m5)
2610
            mstore(0xc0, m6)
2611
            mstore(0xe0, m7)
2612
        }
2613
    }
2614

                            
                        
2615
    function log(bytes32 p0, uint256 p1, address p2) internal pure {
2616
        bytes32 m0;
2617
        bytes32 m1;
2618
        bytes32 m2;
2619
        bytes32 m3;
2620
        bytes32 m4;
2621
        bytes32 m5;
2622
        /// @solidity memory-safe-assembly
2623
        assembly {
2624
            function writeString(pos, w) {
2625
                let length := 0
2626
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2627
                mstore(pos, length)
2628
                let shift := sub(256, shl(3, length))
2629
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2630
            }
2631
            m0 := mload(0x00)
2632
            m1 := mload(0x20)
2633
            m2 := mload(0x40)
2634
            m3 := mload(0x60)
2635
            m4 := mload(0x80)
2636
            m5 := mload(0xa0)
2637
            // Selector of `log(string,uint256,address)`.
2638
            mstore(0x00, 0x1c7ec448)
2639
            mstore(0x20, 0x60)
2640
            mstore(0x40, p1)
2641
            mstore(0x60, p2)
2642
            writeString(0x80, p0)
2643
        }
2644
        _sendLogPayload(0x1c, 0xa4);
2645
        /// @solidity memory-safe-assembly
2646
        assembly {
2647
            mstore(0x00, m0)
2648
            mstore(0x20, m1)
2649
            mstore(0x40, m2)
2650
            mstore(0x60, m3)
2651
            mstore(0x80, m4)
2652
            mstore(0xa0, m5)
2653
        }
2654
    }
2655

                            
                        
2656
    function log(bytes32 p0, uint256 p1, bool p2) internal pure {
2657
        bytes32 m0;
2658
        bytes32 m1;
2659
        bytes32 m2;
2660
        bytes32 m3;
2661
        bytes32 m4;
2662
        bytes32 m5;
2663
        /// @solidity memory-safe-assembly
2664
        assembly {
2665
            function writeString(pos, w) {
2666
                let length := 0
2667
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2668
                mstore(pos, length)
2669
                let shift := sub(256, shl(3, length))
2670
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2671
            }
2672
            m0 := mload(0x00)
2673
            m1 := mload(0x20)
2674
            m2 := mload(0x40)
2675
            m3 := mload(0x60)
2676
            m4 := mload(0x80)
2677
            m5 := mload(0xa0)
2678
            // Selector of `log(string,uint256,bool)`.
2679
            mstore(0x00, 0xca7733b1)
2680
            mstore(0x20, 0x60)
2681
            mstore(0x40, p1)
2682
            mstore(0x60, p2)
2683
            writeString(0x80, p0)
2684
        }
2685
        _sendLogPayload(0x1c, 0xa4);
2686
        /// @solidity memory-safe-assembly
2687
        assembly {
2688
            mstore(0x00, m0)
2689
            mstore(0x20, m1)
2690
            mstore(0x40, m2)
2691
            mstore(0x60, m3)
2692
            mstore(0x80, m4)
2693
            mstore(0xa0, m5)
2694
        }
2695
    }
2696

                            
                        
2697
    function log(bytes32 p0, uint256 p1, uint256 p2) internal pure {
2698
        bytes32 m0;
2699
        bytes32 m1;
2700
        bytes32 m2;
2701
        bytes32 m3;
2702
        bytes32 m4;
2703
        bytes32 m5;
2704
        /// @solidity memory-safe-assembly
2705
        assembly {
2706
            function writeString(pos, w) {
2707
                let length := 0
2708
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2709
                mstore(pos, length)
2710
                let shift := sub(256, shl(3, length))
2711
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2712
            }
2713
            m0 := mload(0x00)
2714
            m1 := mload(0x20)
2715
            m2 := mload(0x40)
2716
            m3 := mload(0x60)
2717
            m4 := mload(0x80)
2718
            m5 := mload(0xa0)
2719
            // Selector of `log(string,uint256,uint256)`.
2720
            mstore(0x00, 0xca47c4eb)
2721
            mstore(0x20, 0x60)
2722
            mstore(0x40, p1)
2723
            mstore(0x60, p2)
2724
            writeString(0x80, p0)
2725
        }
2726
        _sendLogPayload(0x1c, 0xa4);
2727
        /// @solidity memory-safe-assembly
2728
        assembly {
2729
            mstore(0x00, m0)
2730
            mstore(0x20, m1)
2731
            mstore(0x40, m2)
2732
            mstore(0x60, m3)
2733
            mstore(0x80, m4)
2734
            mstore(0xa0, m5)
2735
        }
2736
    }
2737

                            
                        
2738
    function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure {
2739
        bytes32 m0;
2740
        bytes32 m1;
2741
        bytes32 m2;
2742
        bytes32 m3;
2743
        bytes32 m4;
2744
        bytes32 m5;
2745
        bytes32 m6;
2746
        bytes32 m7;
2747
        /// @solidity memory-safe-assembly
2748
        assembly {
2749
            function writeString(pos, w) {
2750
                let length := 0
2751
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2752
                mstore(pos, length)
2753
                let shift := sub(256, shl(3, length))
2754
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2755
            }
2756
            m0 := mload(0x00)
2757
            m1 := mload(0x20)
2758
            m2 := mload(0x40)
2759
            m3 := mload(0x60)
2760
            m4 := mload(0x80)
2761
            m5 := mload(0xa0)
2762
            m6 := mload(0xc0)
2763
            m7 := mload(0xe0)
2764
            // Selector of `log(string,uint256,string)`.
2765
            mstore(0x00, 0x5970e089)
2766
            mstore(0x20, 0x60)
2767
            mstore(0x40, p1)
2768
            mstore(0x60, 0xa0)
2769
            writeString(0x80, p0)
2770
            writeString(0xc0, p2)
2771
        }
2772
        _sendLogPayload(0x1c, 0xe4);
2773
        /// @solidity memory-safe-assembly
2774
        assembly {
2775
            mstore(0x00, m0)
2776
            mstore(0x20, m1)
2777
            mstore(0x40, m2)
2778
            mstore(0x60, m3)
2779
            mstore(0x80, m4)
2780
            mstore(0xa0, m5)
2781
            mstore(0xc0, m6)
2782
            mstore(0xe0, m7)
2783
        }
2784
    }
2785

                            
                        
2786
    function log(bytes32 p0, bytes32 p1, address p2) internal pure {
2787
        bytes32 m0;
2788
        bytes32 m1;
2789
        bytes32 m2;
2790
        bytes32 m3;
2791
        bytes32 m4;
2792
        bytes32 m5;
2793
        bytes32 m6;
2794
        bytes32 m7;
2795
        /// @solidity memory-safe-assembly
2796
        assembly {
2797
            function writeString(pos, w) {
2798
                let length := 0
2799
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2800
                mstore(pos, length)
2801
                let shift := sub(256, shl(3, length))
2802
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2803
            }
2804
            m0 := mload(0x00)
2805
            m1 := mload(0x20)
2806
            m2 := mload(0x40)
2807
            m3 := mload(0x60)
2808
            m4 := mload(0x80)
2809
            m5 := mload(0xa0)
2810
            m6 := mload(0xc0)
2811
            m7 := mload(0xe0)
2812
            // Selector of `log(string,string,address)`.
2813
            mstore(0x00, 0x95ed0195)
2814
            mstore(0x20, 0x60)
2815
            mstore(0x40, 0xa0)
2816
            mstore(0x60, p2)
2817
            writeString(0x80, p0)
2818
            writeString(0xc0, p1)
2819
        }
2820
        _sendLogPayload(0x1c, 0xe4);
2821
        /// @solidity memory-safe-assembly
2822
        assembly {
2823
            mstore(0x00, m0)
2824
            mstore(0x20, m1)
2825
            mstore(0x40, m2)
2826
            mstore(0x60, m3)
2827
            mstore(0x80, m4)
2828
            mstore(0xa0, m5)
2829
            mstore(0xc0, m6)
2830
            mstore(0xe0, m7)
2831
        }
2832
    }
2833

                            
                        
2834
    function log(bytes32 p0, bytes32 p1, bool p2) internal pure {
2835
        bytes32 m0;
2836
        bytes32 m1;
2837
        bytes32 m2;
2838
        bytes32 m3;
2839
        bytes32 m4;
2840
        bytes32 m5;
2841
        bytes32 m6;
2842
        bytes32 m7;
2843
        /// @solidity memory-safe-assembly
2844
        assembly {
2845
            function writeString(pos, w) {
2846
                let length := 0
2847
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2848
                mstore(pos, length)
2849
                let shift := sub(256, shl(3, length))
2850
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2851
            }
2852
            m0 := mload(0x00)
2853
            m1 := mload(0x20)
2854
            m2 := mload(0x40)
2855
            m3 := mload(0x60)
2856
            m4 := mload(0x80)
2857
            m5 := mload(0xa0)
2858
            m6 := mload(0xc0)
2859
            m7 := mload(0xe0)
2860
            // Selector of `log(string,string,bool)`.
2861
            mstore(0x00, 0xb0e0f9b5)
2862
            mstore(0x20, 0x60)
2863
            mstore(0x40, 0xa0)
2864
            mstore(0x60, p2)
2865
            writeString(0x80, p0)
2866
            writeString(0xc0, p1)
2867
        }
2868
        _sendLogPayload(0x1c, 0xe4);
2869
        /// @solidity memory-safe-assembly
2870
        assembly {
2871
            mstore(0x00, m0)
2872
            mstore(0x20, m1)
2873
            mstore(0x40, m2)
2874
            mstore(0x60, m3)
2875
            mstore(0x80, m4)
2876
            mstore(0xa0, m5)
2877
            mstore(0xc0, m6)
2878
            mstore(0xe0, m7)
2879
        }
2880
    }
2881

                            
                        
2882
    function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure {
2883
        bytes32 m0;
2884
        bytes32 m1;
2885
        bytes32 m2;
2886
        bytes32 m3;
2887
        bytes32 m4;
2888
        bytes32 m5;
2889
        bytes32 m6;
2890
        bytes32 m7;
2891
        /// @solidity memory-safe-assembly
2892
        assembly {
2893
            function writeString(pos, w) {
2894
                let length := 0
2895
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2896
                mstore(pos, length)
2897
                let shift := sub(256, shl(3, length))
2898
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2899
            }
2900
            m0 := mload(0x00)
2901
            m1 := mload(0x20)
2902
            m2 := mload(0x40)
2903
            m3 := mload(0x60)
2904
            m4 := mload(0x80)
2905
            m5 := mload(0xa0)
2906
            m6 := mload(0xc0)
2907
            m7 := mload(0xe0)
2908
            // Selector of `log(string,string,uint256)`.
2909
            mstore(0x00, 0x5821efa1)
2910
            mstore(0x20, 0x60)
2911
            mstore(0x40, 0xa0)
2912
            mstore(0x60, p2)
2913
            writeString(0x80, p0)
2914
            writeString(0xc0, p1)
2915
        }
2916
        _sendLogPayload(0x1c, 0xe4);
2917
        /// @solidity memory-safe-assembly
2918
        assembly {
2919
            mstore(0x00, m0)
2920
            mstore(0x20, m1)
2921
            mstore(0x40, m2)
2922
            mstore(0x60, m3)
2923
            mstore(0x80, m4)
2924
            mstore(0xa0, m5)
2925
            mstore(0xc0, m6)
2926
            mstore(0xe0, m7)
2927
        }
2928
    }
2929

                            
                        
2930
    function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure {
2931
        bytes32 m0;
2932
        bytes32 m1;
2933
        bytes32 m2;
2934
        bytes32 m3;
2935
        bytes32 m4;
2936
        bytes32 m5;
2937
        bytes32 m6;
2938
        bytes32 m7;
2939
        bytes32 m8;
2940
        bytes32 m9;
2941
        /// @solidity memory-safe-assembly
2942
        assembly {
2943
            function writeString(pos, w) {
2944
                let length := 0
2945
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
2946
                mstore(pos, length)
2947
                let shift := sub(256, shl(3, length))
2948
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
2949
            }
2950
            m0 := mload(0x00)
2951
            m1 := mload(0x20)
2952
            m2 := mload(0x40)
2953
            m3 := mload(0x60)
2954
            m4 := mload(0x80)
2955
            m5 := mload(0xa0)
2956
            m6 := mload(0xc0)
2957
            m7 := mload(0xe0)
2958
            m8 := mload(0x100)
2959
            m9 := mload(0x120)
2960
            // Selector of `log(string,string,string)`.
2961
            mstore(0x00, 0x2ced7cef)
2962
            mstore(0x20, 0x60)
2963
            mstore(0x40, 0xa0)
2964
            mstore(0x60, 0xe0)
2965
            writeString(0x80, p0)
2966
            writeString(0xc0, p1)
2967
            writeString(0x100, p2)
2968
        }
2969
        _sendLogPayload(0x1c, 0x124);
2970
        /// @solidity memory-safe-assembly
2971
        assembly {
2972
            mstore(0x00, m0)
2973
            mstore(0x20, m1)
2974
            mstore(0x40, m2)
2975
            mstore(0x60, m3)
2976
            mstore(0x80, m4)
2977
            mstore(0xa0, m5)
2978
            mstore(0xc0, m6)
2979
            mstore(0xe0, m7)
2980
            mstore(0x100, m8)
2981
            mstore(0x120, m9)
2982
        }
2983
    }
2984

                            
                        
2985
    function log(address p0, address p1, address p2, address p3) internal pure {
2986
        bytes32 m0;
2987
        bytes32 m1;
2988
        bytes32 m2;
2989
        bytes32 m3;
2990
        bytes32 m4;
2991
        /// @solidity memory-safe-assembly
2992
        assembly {
2993
            m0 := mload(0x00)
2994
            m1 := mload(0x20)
2995
            m2 := mload(0x40)
2996
            m3 := mload(0x60)
2997
            m4 := mload(0x80)
2998
            // Selector of `log(address,address,address,address)`.
2999
            mstore(0x00, 0x665bf134)
3000
            mstore(0x20, p0)
3001
            mstore(0x40, p1)
3002
            mstore(0x60, p2)
3003
            mstore(0x80, p3)
3004
        }
3005
        _sendLogPayload(0x1c, 0x84);
3006
        /// @solidity memory-safe-assembly
3007
        assembly {
3008
            mstore(0x00, m0)
3009
            mstore(0x20, m1)
3010
            mstore(0x40, m2)
3011
            mstore(0x60, m3)
3012
            mstore(0x80, m4)
3013
        }
3014
    }
3015

                            
                        
3016
    function log(address p0, address p1, address p2, bool p3) internal pure {
3017
        bytes32 m0;
3018
        bytes32 m1;
3019
        bytes32 m2;
3020
        bytes32 m3;
3021
        bytes32 m4;
3022
        /// @solidity memory-safe-assembly
3023
        assembly {
3024
            m0 := mload(0x00)
3025
            m1 := mload(0x20)
3026
            m2 := mload(0x40)
3027
            m3 := mload(0x60)
3028
            m4 := mload(0x80)
3029
            // Selector of `log(address,address,address,bool)`.
3030
            mstore(0x00, 0x0e378994)
3031
            mstore(0x20, p0)
3032
            mstore(0x40, p1)
3033
            mstore(0x60, p2)
3034
            mstore(0x80, p3)
3035
        }
3036
        _sendLogPayload(0x1c, 0x84);
3037
        /// @solidity memory-safe-assembly
3038
        assembly {
3039
            mstore(0x00, m0)
3040
            mstore(0x20, m1)
3041
            mstore(0x40, m2)
3042
            mstore(0x60, m3)
3043
            mstore(0x80, m4)
3044
        }
3045
    }
3046

                            
                        
3047
    function log(address p0, address p1, address p2, uint256 p3) internal pure {
3048
        bytes32 m0;
3049
        bytes32 m1;
3050
        bytes32 m2;
3051
        bytes32 m3;
3052
        bytes32 m4;
3053
        /// @solidity memory-safe-assembly
3054
        assembly {
3055
            m0 := mload(0x00)
3056
            m1 := mload(0x20)
3057
            m2 := mload(0x40)
3058
            m3 := mload(0x60)
3059
            m4 := mload(0x80)
3060
            // Selector of `log(address,address,address,uint256)`.
3061
            mstore(0x00, 0x94250d77)
3062
            mstore(0x20, p0)
3063
            mstore(0x40, p1)
3064
            mstore(0x60, p2)
3065
            mstore(0x80, p3)
3066
        }
3067
        _sendLogPayload(0x1c, 0x84);
3068
        /// @solidity memory-safe-assembly
3069
        assembly {
3070
            mstore(0x00, m0)
3071
            mstore(0x20, m1)
3072
            mstore(0x40, m2)
3073
            mstore(0x60, m3)
3074
            mstore(0x80, m4)
3075
        }
3076
    }
3077

                            
                        
3078
    function log(address p0, address p1, address p2, bytes32 p3) internal pure {
3079
        bytes32 m0;
3080
        bytes32 m1;
3081
        bytes32 m2;
3082
        bytes32 m3;
3083
        bytes32 m4;
3084
        bytes32 m5;
3085
        bytes32 m6;
3086
        /// @solidity memory-safe-assembly
3087
        assembly {
3088
            function writeString(pos, w) {
3089
                let length := 0
3090
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3091
                mstore(pos, length)
3092
                let shift := sub(256, shl(3, length))
3093
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3094
            }
3095
            m0 := mload(0x00)
3096
            m1 := mload(0x20)
3097
            m2 := mload(0x40)
3098
            m3 := mload(0x60)
3099
            m4 := mload(0x80)
3100
            m5 := mload(0xa0)
3101
            m6 := mload(0xc0)
3102
            // Selector of `log(address,address,address,string)`.
3103
            mstore(0x00, 0xf808da20)
3104
            mstore(0x20, p0)
3105
            mstore(0x40, p1)
3106
            mstore(0x60, p2)
3107
            mstore(0x80, 0x80)
3108
            writeString(0xa0, p3)
3109
        }
3110
        _sendLogPayload(0x1c, 0xc4);
3111
        /// @solidity memory-safe-assembly
3112
        assembly {
3113
            mstore(0x00, m0)
3114
            mstore(0x20, m1)
3115
            mstore(0x40, m2)
3116
            mstore(0x60, m3)
3117
            mstore(0x80, m4)
3118
            mstore(0xa0, m5)
3119
            mstore(0xc0, m6)
3120
        }
3121
    }
3122

                            
                        
3123
    function log(address p0, address p1, bool p2, address p3) internal pure {
3124
        bytes32 m0;
3125
        bytes32 m1;
3126
        bytes32 m2;
3127
        bytes32 m3;
3128
        bytes32 m4;
3129
        /// @solidity memory-safe-assembly
3130
        assembly {
3131
            m0 := mload(0x00)
3132
            m1 := mload(0x20)
3133
            m2 := mload(0x40)
3134
            m3 := mload(0x60)
3135
            m4 := mload(0x80)
3136
            // Selector of `log(address,address,bool,address)`.
3137
            mstore(0x00, 0x9f1bc36e)
3138
            mstore(0x20, p0)
3139
            mstore(0x40, p1)
3140
            mstore(0x60, p2)
3141
            mstore(0x80, p3)
3142
        }
3143
        _sendLogPayload(0x1c, 0x84);
3144
        /// @solidity memory-safe-assembly
3145
        assembly {
3146
            mstore(0x00, m0)
3147
            mstore(0x20, m1)
3148
            mstore(0x40, m2)
3149
            mstore(0x60, m3)
3150
            mstore(0x80, m4)
3151
        }
3152
    }
3153

                            
                        
3154
    function log(address p0, address p1, bool p2, bool p3) internal pure {
3155
        bytes32 m0;
3156
        bytes32 m1;
3157
        bytes32 m2;
3158
        bytes32 m3;
3159
        bytes32 m4;
3160
        /// @solidity memory-safe-assembly
3161
        assembly {
3162
            m0 := mload(0x00)
3163
            m1 := mload(0x20)
3164
            m2 := mload(0x40)
3165
            m3 := mload(0x60)
3166
            m4 := mload(0x80)
3167
            // Selector of `log(address,address,bool,bool)`.
3168
            mstore(0x00, 0x2cd4134a)
3169
            mstore(0x20, p0)
3170
            mstore(0x40, p1)
3171
            mstore(0x60, p2)
3172
            mstore(0x80, p3)
3173
        }
3174
        _sendLogPayload(0x1c, 0x84);
3175
        /// @solidity memory-safe-assembly
3176
        assembly {
3177
            mstore(0x00, m0)
3178
            mstore(0x20, m1)
3179
            mstore(0x40, m2)
3180
            mstore(0x60, m3)
3181
            mstore(0x80, m4)
3182
        }
3183
    }
3184

                            
                        
3185
    function log(address p0, address p1, bool p2, uint256 p3) internal pure {
3186
        bytes32 m0;
3187
        bytes32 m1;
3188
        bytes32 m2;
3189
        bytes32 m3;
3190
        bytes32 m4;
3191
        /// @solidity memory-safe-assembly
3192
        assembly {
3193
            m0 := mload(0x00)
3194
            m1 := mload(0x20)
3195
            m2 := mload(0x40)
3196
            m3 := mload(0x60)
3197
            m4 := mload(0x80)
3198
            // Selector of `log(address,address,bool,uint256)`.
3199
            mstore(0x00, 0x3971e78c)
3200
            mstore(0x20, p0)
3201
            mstore(0x40, p1)
3202
            mstore(0x60, p2)
3203
            mstore(0x80, p3)
3204
        }
3205
        _sendLogPayload(0x1c, 0x84);
3206
        /// @solidity memory-safe-assembly
3207
        assembly {
3208
            mstore(0x00, m0)
3209
            mstore(0x20, m1)
3210
            mstore(0x40, m2)
3211
            mstore(0x60, m3)
3212
            mstore(0x80, m4)
3213
        }
3214
    }
3215

                            
                        
3216
    function log(address p0, address p1, bool p2, bytes32 p3) internal pure {
3217
        bytes32 m0;
3218
        bytes32 m1;
3219
        bytes32 m2;
3220
        bytes32 m3;
3221
        bytes32 m4;
3222
        bytes32 m5;
3223
        bytes32 m6;
3224
        /// @solidity memory-safe-assembly
3225
        assembly {
3226
            function writeString(pos, w) {
3227
                let length := 0
3228
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3229
                mstore(pos, length)
3230
                let shift := sub(256, shl(3, length))
3231
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3232
            }
3233
            m0 := mload(0x00)
3234
            m1 := mload(0x20)
3235
            m2 := mload(0x40)
3236
            m3 := mload(0x60)
3237
            m4 := mload(0x80)
3238
            m5 := mload(0xa0)
3239
            m6 := mload(0xc0)
3240
            // Selector of `log(address,address,bool,string)`.
3241
            mstore(0x00, 0xaa6540c8)
3242
            mstore(0x20, p0)
3243
            mstore(0x40, p1)
3244
            mstore(0x60, p2)
3245
            mstore(0x80, 0x80)
3246
            writeString(0xa0, p3)
3247
        }
3248
        _sendLogPayload(0x1c, 0xc4);
3249
        /// @solidity memory-safe-assembly
3250
        assembly {
3251
            mstore(0x00, m0)
3252
            mstore(0x20, m1)
3253
            mstore(0x40, m2)
3254
            mstore(0x60, m3)
3255
            mstore(0x80, m4)
3256
            mstore(0xa0, m5)
3257
            mstore(0xc0, m6)
3258
        }
3259
    }
3260

                            
                        
3261
    function log(address p0, address p1, uint256 p2, address p3) internal pure {
3262
        bytes32 m0;
3263
        bytes32 m1;
3264
        bytes32 m2;
3265
        bytes32 m3;
3266
        bytes32 m4;
3267
        /// @solidity memory-safe-assembly
3268
        assembly {
3269
            m0 := mload(0x00)
3270
            m1 := mload(0x20)
3271
            m2 := mload(0x40)
3272
            m3 := mload(0x60)
3273
            m4 := mload(0x80)
3274
            // Selector of `log(address,address,uint256,address)`.
3275
            mstore(0x00, 0x8da6def5)
3276
            mstore(0x20, p0)
3277
            mstore(0x40, p1)
3278
            mstore(0x60, p2)
3279
            mstore(0x80, p3)
3280
        }
3281
        _sendLogPayload(0x1c, 0x84);
3282
        /// @solidity memory-safe-assembly
3283
        assembly {
3284
            mstore(0x00, m0)
3285
            mstore(0x20, m1)
3286
            mstore(0x40, m2)
3287
            mstore(0x60, m3)
3288
            mstore(0x80, m4)
3289
        }
3290
    }
3291

                            
                        
3292
    function log(address p0, address p1, uint256 p2, bool p3) internal pure {
3293
        bytes32 m0;
3294
        bytes32 m1;
3295
        bytes32 m2;
3296
        bytes32 m3;
3297
        bytes32 m4;
3298
        /// @solidity memory-safe-assembly
3299
        assembly {
3300
            m0 := mload(0x00)
3301
            m1 := mload(0x20)
3302
            m2 := mload(0x40)
3303
            m3 := mload(0x60)
3304
            m4 := mload(0x80)
3305
            // Selector of `log(address,address,uint256,bool)`.
3306
            mstore(0x00, 0x9b4254e2)
3307
            mstore(0x20, p0)
3308
            mstore(0x40, p1)
3309
            mstore(0x60, p2)
3310
            mstore(0x80, p3)
3311
        }
3312
        _sendLogPayload(0x1c, 0x84);
3313
        /// @solidity memory-safe-assembly
3314
        assembly {
3315
            mstore(0x00, m0)
3316
            mstore(0x20, m1)
3317
            mstore(0x40, m2)
3318
            mstore(0x60, m3)
3319
            mstore(0x80, m4)
3320
        }
3321
    }
3322

                            
                        
3323
    function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
3324
        bytes32 m0;
3325
        bytes32 m1;
3326
        bytes32 m2;
3327
        bytes32 m3;
3328
        bytes32 m4;
3329
        /// @solidity memory-safe-assembly
3330
        assembly {
3331
            m0 := mload(0x00)
3332
            m1 := mload(0x20)
3333
            m2 := mload(0x40)
3334
            m3 := mload(0x60)
3335
            m4 := mload(0x80)
3336
            // Selector of `log(address,address,uint256,uint256)`.
3337
            mstore(0x00, 0xbe553481)
3338
            mstore(0x20, p0)
3339
            mstore(0x40, p1)
3340
            mstore(0x60, p2)
3341
            mstore(0x80, p3)
3342
        }
3343
        _sendLogPayload(0x1c, 0x84);
3344
        /// @solidity memory-safe-assembly
3345
        assembly {
3346
            mstore(0x00, m0)
3347
            mstore(0x20, m1)
3348
            mstore(0x40, m2)
3349
            mstore(0x60, m3)
3350
            mstore(0x80, m4)
3351
        }
3352
    }
3353

                            
                        
3354
    function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure {
3355
        bytes32 m0;
3356
        bytes32 m1;
3357
        bytes32 m2;
3358
        bytes32 m3;
3359
        bytes32 m4;
3360
        bytes32 m5;
3361
        bytes32 m6;
3362
        /// @solidity memory-safe-assembly
3363
        assembly {
3364
            function writeString(pos, w) {
3365
                let length := 0
3366
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3367
                mstore(pos, length)
3368
                let shift := sub(256, shl(3, length))
3369
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3370
            }
3371
            m0 := mload(0x00)
3372
            m1 := mload(0x20)
3373
            m2 := mload(0x40)
3374
            m3 := mload(0x60)
3375
            m4 := mload(0x80)
3376
            m5 := mload(0xa0)
3377
            m6 := mload(0xc0)
3378
            // Selector of `log(address,address,uint256,string)`.
3379
            mstore(0x00, 0xfdb4f990)
3380
            mstore(0x20, p0)
3381
            mstore(0x40, p1)
3382
            mstore(0x60, p2)
3383
            mstore(0x80, 0x80)
3384
            writeString(0xa0, p3)
3385
        }
3386
        _sendLogPayload(0x1c, 0xc4);
3387
        /// @solidity memory-safe-assembly
3388
        assembly {
3389
            mstore(0x00, m0)
3390
            mstore(0x20, m1)
3391
            mstore(0x40, m2)
3392
            mstore(0x60, m3)
3393
            mstore(0x80, m4)
3394
            mstore(0xa0, m5)
3395
            mstore(0xc0, m6)
3396
        }
3397
    }
3398

                            
                        
3399
    function log(address p0, address p1, bytes32 p2, address p3) internal pure {
3400
        bytes32 m0;
3401
        bytes32 m1;
3402
        bytes32 m2;
3403
        bytes32 m3;
3404
        bytes32 m4;
3405
        bytes32 m5;
3406
        bytes32 m6;
3407
        /// @solidity memory-safe-assembly
3408
        assembly {
3409
            function writeString(pos, w) {
3410
                let length := 0
3411
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3412
                mstore(pos, length)
3413
                let shift := sub(256, shl(3, length))
3414
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3415
            }
3416
            m0 := mload(0x00)
3417
            m1 := mload(0x20)
3418
            m2 := mload(0x40)
3419
            m3 := mload(0x60)
3420
            m4 := mload(0x80)
3421
            m5 := mload(0xa0)
3422
            m6 := mload(0xc0)
3423
            // Selector of `log(address,address,string,address)`.
3424
            mstore(0x00, 0x8f736d16)
3425
            mstore(0x20, p0)
3426
            mstore(0x40, p1)
3427
            mstore(0x60, 0x80)
3428
            mstore(0x80, p3)
3429
            writeString(0xa0, p2)
3430
        }
3431
        _sendLogPayload(0x1c, 0xc4);
3432
        /// @solidity memory-safe-assembly
3433
        assembly {
3434
            mstore(0x00, m0)
3435
            mstore(0x20, m1)
3436
            mstore(0x40, m2)
3437
            mstore(0x60, m3)
3438
            mstore(0x80, m4)
3439
            mstore(0xa0, m5)
3440
            mstore(0xc0, m6)
3441
        }
3442
    }
3443

                            
                        
3444
    function log(address p0, address p1, bytes32 p2, bool p3) internal pure {
3445
        bytes32 m0;
3446
        bytes32 m1;
3447
        bytes32 m2;
3448
        bytes32 m3;
3449
        bytes32 m4;
3450
        bytes32 m5;
3451
        bytes32 m6;
3452
        /// @solidity memory-safe-assembly
3453
        assembly {
3454
            function writeString(pos, w) {
3455
                let length := 0
3456
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3457
                mstore(pos, length)
3458
                let shift := sub(256, shl(3, length))
3459
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3460
            }
3461
            m0 := mload(0x00)
3462
            m1 := mload(0x20)
3463
            m2 := mload(0x40)
3464
            m3 := mload(0x60)
3465
            m4 := mload(0x80)
3466
            m5 := mload(0xa0)
3467
            m6 := mload(0xc0)
3468
            // Selector of `log(address,address,string,bool)`.
3469
            mstore(0x00, 0x6f1a594e)
3470
            mstore(0x20, p0)
3471
            mstore(0x40, p1)
3472
            mstore(0x60, 0x80)
3473
            mstore(0x80, p3)
3474
            writeString(0xa0, p2)
3475
        }
3476
        _sendLogPayload(0x1c, 0xc4);
3477
        /// @solidity memory-safe-assembly
3478
        assembly {
3479
            mstore(0x00, m0)
3480
            mstore(0x20, m1)
3481
            mstore(0x40, m2)
3482
            mstore(0x60, m3)
3483
            mstore(0x80, m4)
3484
            mstore(0xa0, m5)
3485
            mstore(0xc0, m6)
3486
        }
3487
    }
3488

                            
                        
3489
    function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure {
3490
        bytes32 m0;
3491
        bytes32 m1;
3492
        bytes32 m2;
3493
        bytes32 m3;
3494
        bytes32 m4;
3495
        bytes32 m5;
3496
        bytes32 m6;
3497
        /// @solidity memory-safe-assembly
3498
        assembly {
3499
            function writeString(pos, w) {
3500
                let length := 0
3501
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3502
                mstore(pos, length)
3503
                let shift := sub(256, shl(3, length))
3504
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3505
            }
3506
            m0 := mload(0x00)
3507
            m1 := mload(0x20)
3508
            m2 := mload(0x40)
3509
            m3 := mload(0x60)
3510
            m4 := mload(0x80)
3511
            m5 := mload(0xa0)
3512
            m6 := mload(0xc0)
3513
            // Selector of `log(address,address,string,uint256)`.
3514
            mstore(0x00, 0xef1cefe7)
3515
            mstore(0x20, p0)
3516
            mstore(0x40, p1)
3517
            mstore(0x60, 0x80)
3518
            mstore(0x80, p3)
3519
            writeString(0xa0, p2)
3520
        }
3521
        _sendLogPayload(0x1c, 0xc4);
3522
        /// @solidity memory-safe-assembly
3523
        assembly {
3524
            mstore(0x00, m0)
3525
            mstore(0x20, m1)
3526
            mstore(0x40, m2)
3527
            mstore(0x60, m3)
3528
            mstore(0x80, m4)
3529
            mstore(0xa0, m5)
3530
            mstore(0xc0, m6)
3531
        }
3532
    }
3533

                            
                        
3534
    function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure {
3535
        bytes32 m0;
3536
        bytes32 m1;
3537
        bytes32 m2;
3538
        bytes32 m3;
3539
        bytes32 m4;
3540
        bytes32 m5;
3541
        bytes32 m6;
3542
        bytes32 m7;
3543
        bytes32 m8;
3544
        /// @solidity memory-safe-assembly
3545
        assembly {
3546
            function writeString(pos, w) {
3547
                let length := 0
3548
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3549
                mstore(pos, length)
3550
                let shift := sub(256, shl(3, length))
3551
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3552
            }
3553
            m0 := mload(0x00)
3554
            m1 := mload(0x20)
3555
            m2 := mload(0x40)
3556
            m3 := mload(0x60)
3557
            m4 := mload(0x80)
3558
            m5 := mload(0xa0)
3559
            m6 := mload(0xc0)
3560
            m7 := mload(0xe0)
3561
            m8 := mload(0x100)
3562
            // Selector of `log(address,address,string,string)`.
3563
            mstore(0x00, 0x21bdaf25)
3564
            mstore(0x20, p0)
3565
            mstore(0x40, p1)
3566
            mstore(0x60, 0x80)
3567
            mstore(0x80, 0xc0)
3568
            writeString(0xa0, p2)
3569
            writeString(0xe0, p3)
3570
        }
3571
        _sendLogPayload(0x1c, 0x104);
3572
        /// @solidity memory-safe-assembly
3573
        assembly {
3574
            mstore(0x00, m0)
3575
            mstore(0x20, m1)
3576
            mstore(0x40, m2)
3577
            mstore(0x60, m3)
3578
            mstore(0x80, m4)
3579
            mstore(0xa0, m5)
3580
            mstore(0xc0, m6)
3581
            mstore(0xe0, m7)
3582
            mstore(0x100, m8)
3583
        }
3584
    }
3585

                            
                        
3586
    function log(address p0, bool p1, address p2, address p3) internal pure {
3587
        bytes32 m0;
3588
        bytes32 m1;
3589
        bytes32 m2;
3590
        bytes32 m3;
3591
        bytes32 m4;
3592
        /// @solidity memory-safe-assembly
3593
        assembly {
3594
            m0 := mload(0x00)
3595
            m1 := mload(0x20)
3596
            m2 := mload(0x40)
3597
            m3 := mload(0x60)
3598
            m4 := mload(0x80)
3599
            // Selector of `log(address,bool,address,address)`.
3600
            mstore(0x00, 0x660375dd)
3601
            mstore(0x20, p0)
3602
            mstore(0x40, p1)
3603
            mstore(0x60, p2)
3604
            mstore(0x80, p3)
3605
        }
3606
        _sendLogPayload(0x1c, 0x84);
3607
        /// @solidity memory-safe-assembly
3608
        assembly {
3609
            mstore(0x00, m0)
3610
            mstore(0x20, m1)
3611
            mstore(0x40, m2)
3612
            mstore(0x60, m3)
3613
            mstore(0x80, m4)
3614
        }
3615
    }
3616

                            
                        
3617
    function log(address p0, bool p1, address p2, bool p3) internal pure {
3618
        bytes32 m0;
3619
        bytes32 m1;
3620
        bytes32 m2;
3621
        bytes32 m3;
3622
        bytes32 m4;
3623
        /// @solidity memory-safe-assembly
3624
        assembly {
3625
            m0 := mload(0x00)
3626
            m1 := mload(0x20)
3627
            m2 := mload(0x40)
3628
            m3 := mload(0x60)
3629
            m4 := mload(0x80)
3630
            // Selector of `log(address,bool,address,bool)`.
3631
            mstore(0x00, 0xa6f50b0f)
3632
            mstore(0x20, p0)
3633
            mstore(0x40, p1)
3634
            mstore(0x60, p2)
3635
            mstore(0x80, p3)
3636
        }
3637
        _sendLogPayload(0x1c, 0x84);
3638
        /// @solidity memory-safe-assembly
3639
        assembly {
3640
            mstore(0x00, m0)
3641
            mstore(0x20, m1)
3642
            mstore(0x40, m2)
3643
            mstore(0x60, m3)
3644
            mstore(0x80, m4)
3645
        }
3646
    }
3647

                            
                        
3648
    function log(address p0, bool p1, address p2, uint256 p3) internal pure {
3649
        bytes32 m0;
3650
        bytes32 m1;
3651
        bytes32 m2;
3652
        bytes32 m3;
3653
        bytes32 m4;
3654
        /// @solidity memory-safe-assembly
3655
        assembly {
3656
            m0 := mload(0x00)
3657
            m1 := mload(0x20)
3658
            m2 := mload(0x40)
3659
            m3 := mload(0x60)
3660
            m4 := mload(0x80)
3661
            // Selector of `log(address,bool,address,uint256)`.
3662
            mstore(0x00, 0xa75c59de)
3663
            mstore(0x20, p0)
3664
            mstore(0x40, p1)
3665
            mstore(0x60, p2)
3666
            mstore(0x80, p3)
3667
        }
3668
        _sendLogPayload(0x1c, 0x84);
3669
        /// @solidity memory-safe-assembly
3670
        assembly {
3671
            mstore(0x00, m0)
3672
            mstore(0x20, m1)
3673
            mstore(0x40, m2)
3674
            mstore(0x60, m3)
3675
            mstore(0x80, m4)
3676
        }
3677
    }
3678

                            
                        
3679
    function log(address p0, bool p1, address p2, bytes32 p3) internal pure {
3680
        bytes32 m0;
3681
        bytes32 m1;
3682
        bytes32 m2;
3683
        bytes32 m3;
3684
        bytes32 m4;
3685
        bytes32 m5;
3686
        bytes32 m6;
3687
        /// @solidity memory-safe-assembly
3688
        assembly {
3689
            function writeString(pos, w) {
3690
                let length := 0
3691
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3692
                mstore(pos, length)
3693
                let shift := sub(256, shl(3, length))
3694
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3695
            }
3696
            m0 := mload(0x00)
3697
            m1 := mload(0x20)
3698
            m2 := mload(0x40)
3699
            m3 := mload(0x60)
3700
            m4 := mload(0x80)
3701
            m5 := mload(0xa0)
3702
            m6 := mload(0xc0)
3703
            // Selector of `log(address,bool,address,string)`.
3704
            mstore(0x00, 0x2dd778e6)
3705
            mstore(0x20, p0)
3706
            mstore(0x40, p1)
3707
            mstore(0x60, p2)
3708
            mstore(0x80, 0x80)
3709
            writeString(0xa0, p3)
3710
        }
3711
        _sendLogPayload(0x1c, 0xc4);
3712
        /// @solidity memory-safe-assembly
3713
        assembly {
3714
            mstore(0x00, m0)
3715
            mstore(0x20, m1)
3716
            mstore(0x40, m2)
3717
            mstore(0x60, m3)
3718
            mstore(0x80, m4)
3719
            mstore(0xa0, m5)
3720
            mstore(0xc0, m6)
3721
        }
3722
    }
3723

                            
                        
3724
    function log(address p0, bool p1, bool p2, address p3) internal pure {
3725
        bytes32 m0;
3726
        bytes32 m1;
3727
        bytes32 m2;
3728
        bytes32 m3;
3729
        bytes32 m4;
3730
        /// @solidity memory-safe-assembly
3731
        assembly {
3732
            m0 := mload(0x00)
3733
            m1 := mload(0x20)
3734
            m2 := mload(0x40)
3735
            m3 := mload(0x60)
3736
            m4 := mload(0x80)
3737
            // Selector of `log(address,bool,bool,address)`.
3738
            mstore(0x00, 0xcf394485)
3739
            mstore(0x20, p0)
3740
            mstore(0x40, p1)
3741
            mstore(0x60, p2)
3742
            mstore(0x80, p3)
3743
        }
3744
        _sendLogPayload(0x1c, 0x84);
3745
        /// @solidity memory-safe-assembly
3746
        assembly {
3747
            mstore(0x00, m0)
3748
            mstore(0x20, m1)
3749
            mstore(0x40, m2)
3750
            mstore(0x60, m3)
3751
            mstore(0x80, m4)
3752
        }
3753
    }
3754

                            
                        
3755
    function log(address p0, bool p1, bool p2, bool p3) internal pure {
3756
        bytes32 m0;
3757
        bytes32 m1;
3758
        bytes32 m2;
3759
        bytes32 m3;
3760
        bytes32 m4;
3761
        /// @solidity memory-safe-assembly
3762
        assembly {
3763
            m0 := mload(0x00)
3764
            m1 := mload(0x20)
3765
            m2 := mload(0x40)
3766
            m3 := mload(0x60)
3767
            m4 := mload(0x80)
3768
            // Selector of `log(address,bool,bool,bool)`.
3769
            mstore(0x00, 0xcac43479)
3770
            mstore(0x20, p0)
3771
            mstore(0x40, p1)
3772
            mstore(0x60, p2)
3773
            mstore(0x80, p3)
3774
        }
3775
        _sendLogPayload(0x1c, 0x84);
3776
        /// @solidity memory-safe-assembly
3777
        assembly {
3778
            mstore(0x00, m0)
3779
            mstore(0x20, m1)
3780
            mstore(0x40, m2)
3781
            mstore(0x60, m3)
3782
            mstore(0x80, m4)
3783
        }
3784
    }
3785

                            
                        
3786
    function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
3787
        bytes32 m0;
3788
        bytes32 m1;
3789
        bytes32 m2;
3790
        bytes32 m3;
3791
        bytes32 m4;
3792
        /// @solidity memory-safe-assembly
3793
        assembly {
3794
            m0 := mload(0x00)
3795
            m1 := mload(0x20)
3796
            m2 := mload(0x40)
3797
            m3 := mload(0x60)
3798
            m4 := mload(0x80)
3799
            // Selector of `log(address,bool,bool,uint256)`.
3800
            mstore(0x00, 0x8c4e5de6)
3801
            mstore(0x20, p0)
3802
            mstore(0x40, p1)
3803
            mstore(0x60, p2)
3804
            mstore(0x80, p3)
3805
        }
3806
        _sendLogPayload(0x1c, 0x84);
3807
        /// @solidity memory-safe-assembly
3808
        assembly {
3809
            mstore(0x00, m0)
3810
            mstore(0x20, m1)
3811
            mstore(0x40, m2)
3812
            mstore(0x60, m3)
3813
            mstore(0x80, m4)
3814
        }
3815
    }
3816

                            
                        
3817
    function log(address p0, bool p1, bool p2, bytes32 p3) internal pure {
3818
        bytes32 m0;
3819
        bytes32 m1;
3820
        bytes32 m2;
3821
        bytes32 m3;
3822
        bytes32 m4;
3823
        bytes32 m5;
3824
        bytes32 m6;
3825
        /// @solidity memory-safe-assembly
3826
        assembly {
3827
            function writeString(pos, w) {
3828
                let length := 0
3829
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3830
                mstore(pos, length)
3831
                let shift := sub(256, shl(3, length))
3832
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3833
            }
3834
            m0 := mload(0x00)
3835
            m1 := mload(0x20)
3836
            m2 := mload(0x40)
3837
            m3 := mload(0x60)
3838
            m4 := mload(0x80)
3839
            m5 := mload(0xa0)
3840
            m6 := mload(0xc0)
3841
            // Selector of `log(address,bool,bool,string)`.
3842
            mstore(0x00, 0xdfc4a2e8)
3843
            mstore(0x20, p0)
3844
            mstore(0x40, p1)
3845
            mstore(0x60, p2)
3846
            mstore(0x80, 0x80)
3847
            writeString(0xa0, p3)
3848
        }
3849
        _sendLogPayload(0x1c, 0xc4);
3850
        /// @solidity memory-safe-assembly
3851
        assembly {
3852
            mstore(0x00, m0)
3853
            mstore(0x20, m1)
3854
            mstore(0x40, m2)
3855
            mstore(0x60, m3)
3856
            mstore(0x80, m4)
3857
            mstore(0xa0, m5)
3858
            mstore(0xc0, m6)
3859
        }
3860
    }
3861

                            
                        
3862
    function log(address p0, bool p1, uint256 p2, address p3) internal pure {
3863
        bytes32 m0;
3864
        bytes32 m1;
3865
        bytes32 m2;
3866
        bytes32 m3;
3867
        bytes32 m4;
3868
        /// @solidity memory-safe-assembly
3869
        assembly {
3870
            m0 := mload(0x00)
3871
            m1 := mload(0x20)
3872
            m2 := mload(0x40)
3873
            m3 := mload(0x60)
3874
            m4 := mload(0x80)
3875
            // Selector of `log(address,bool,uint256,address)`.
3876
            mstore(0x00, 0xccf790a1)
3877
            mstore(0x20, p0)
3878
            mstore(0x40, p1)
3879
            mstore(0x60, p2)
3880
            mstore(0x80, p3)
3881
        }
3882
        _sendLogPayload(0x1c, 0x84);
3883
        /// @solidity memory-safe-assembly
3884
        assembly {
3885
            mstore(0x00, m0)
3886
            mstore(0x20, m1)
3887
            mstore(0x40, m2)
3888
            mstore(0x60, m3)
3889
            mstore(0x80, m4)
3890
        }
3891
    }
3892

                            
                        
3893
    function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
3894
        bytes32 m0;
3895
        bytes32 m1;
3896
        bytes32 m2;
3897
        bytes32 m3;
3898
        bytes32 m4;
3899
        /// @solidity memory-safe-assembly
3900
        assembly {
3901
            m0 := mload(0x00)
3902
            m1 := mload(0x20)
3903
            m2 := mload(0x40)
3904
            m3 := mload(0x60)
3905
            m4 := mload(0x80)
3906
            // Selector of `log(address,bool,uint256,bool)`.
3907
            mstore(0x00, 0xc4643e20)
3908
            mstore(0x20, p0)
3909
            mstore(0x40, p1)
3910
            mstore(0x60, p2)
3911
            mstore(0x80, p3)
3912
        }
3913
        _sendLogPayload(0x1c, 0x84);
3914
        /// @solidity memory-safe-assembly
3915
        assembly {
3916
            mstore(0x00, m0)
3917
            mstore(0x20, m1)
3918
            mstore(0x40, m2)
3919
            mstore(0x60, m3)
3920
            mstore(0x80, m4)
3921
        }
3922
    }
3923

                            
                        
3924
    function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
3925
        bytes32 m0;
3926
        bytes32 m1;
3927
        bytes32 m2;
3928
        bytes32 m3;
3929
        bytes32 m4;
3930
        /// @solidity memory-safe-assembly
3931
        assembly {
3932
            m0 := mload(0x00)
3933
            m1 := mload(0x20)
3934
            m2 := mload(0x40)
3935
            m3 := mload(0x60)
3936
            m4 := mload(0x80)
3937
            // Selector of `log(address,bool,uint256,uint256)`.
3938
            mstore(0x00, 0x386ff5f4)
3939
            mstore(0x20, p0)
3940
            mstore(0x40, p1)
3941
            mstore(0x60, p2)
3942
            mstore(0x80, p3)
3943
        }
3944
        _sendLogPayload(0x1c, 0x84);
3945
        /// @solidity memory-safe-assembly
3946
        assembly {
3947
            mstore(0x00, m0)
3948
            mstore(0x20, m1)
3949
            mstore(0x40, m2)
3950
            mstore(0x60, m3)
3951
            mstore(0x80, m4)
3952
        }
3953
    }
3954

                            
                        
3955
    function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure {
3956
        bytes32 m0;
3957
        bytes32 m1;
3958
        bytes32 m2;
3959
        bytes32 m3;
3960
        bytes32 m4;
3961
        bytes32 m5;
3962
        bytes32 m6;
3963
        /// @solidity memory-safe-assembly
3964
        assembly {
3965
            function writeString(pos, w) {
3966
                let length := 0
3967
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
3968
                mstore(pos, length)
3969
                let shift := sub(256, shl(3, length))
3970
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
3971
            }
3972
            m0 := mload(0x00)
3973
            m1 := mload(0x20)
3974
            m2 := mload(0x40)
3975
            m3 := mload(0x60)
3976
            m4 := mload(0x80)
3977
            m5 := mload(0xa0)
3978
            m6 := mload(0xc0)
3979
            // Selector of `log(address,bool,uint256,string)`.
3980
            mstore(0x00, 0x0aa6cfad)
3981
            mstore(0x20, p0)
3982
            mstore(0x40, p1)
3983
            mstore(0x60, p2)
3984
            mstore(0x80, 0x80)
3985
            writeString(0xa0, p3)
3986
        }
3987
        _sendLogPayload(0x1c, 0xc4);
3988
        /// @solidity memory-safe-assembly
3989
        assembly {
3990
            mstore(0x00, m0)
3991
            mstore(0x20, m1)
3992
            mstore(0x40, m2)
3993
            mstore(0x60, m3)
3994
            mstore(0x80, m4)
3995
            mstore(0xa0, m5)
3996
            mstore(0xc0, m6)
3997
        }
3998
    }
3999

                            
                        
4000
    function log(address p0, bool p1, bytes32 p2, address p3) internal pure {
4001
        bytes32 m0;
4002
        bytes32 m1;
4003
        bytes32 m2;
4004
        bytes32 m3;
4005
        bytes32 m4;
4006
        bytes32 m5;
4007
        bytes32 m6;
4008
        /// @solidity memory-safe-assembly
4009
        assembly {
4010
            function writeString(pos, w) {
4011
                let length := 0
4012
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4013
                mstore(pos, length)
4014
                let shift := sub(256, shl(3, length))
4015
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4016
            }
4017
            m0 := mload(0x00)
4018
            m1 := mload(0x20)
4019
            m2 := mload(0x40)
4020
            m3 := mload(0x60)
4021
            m4 := mload(0x80)
4022
            m5 := mload(0xa0)
4023
            m6 := mload(0xc0)
4024
            // Selector of `log(address,bool,string,address)`.
4025
            mstore(0x00, 0x19fd4956)
4026
            mstore(0x20, p0)
4027
            mstore(0x40, p1)
4028
            mstore(0x60, 0x80)
4029
            mstore(0x80, p3)
4030
            writeString(0xa0, p2)
4031
        }
4032
        _sendLogPayload(0x1c, 0xc4);
4033
        /// @solidity memory-safe-assembly
4034
        assembly {
4035
            mstore(0x00, m0)
4036
            mstore(0x20, m1)
4037
            mstore(0x40, m2)
4038
            mstore(0x60, m3)
4039
            mstore(0x80, m4)
4040
            mstore(0xa0, m5)
4041
            mstore(0xc0, m6)
4042
        }
4043
    }
4044

                            
                        
4045
    function log(address p0, bool p1, bytes32 p2, bool p3) internal pure {
4046
        bytes32 m0;
4047
        bytes32 m1;
4048
        bytes32 m2;
4049
        bytes32 m3;
4050
        bytes32 m4;
4051
        bytes32 m5;
4052
        bytes32 m6;
4053
        /// @solidity memory-safe-assembly
4054
        assembly {
4055
            function writeString(pos, w) {
4056
                let length := 0
4057
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4058
                mstore(pos, length)
4059
                let shift := sub(256, shl(3, length))
4060
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4061
            }
4062
            m0 := mload(0x00)
4063
            m1 := mload(0x20)
4064
            m2 := mload(0x40)
4065
            m3 := mload(0x60)
4066
            m4 := mload(0x80)
4067
            m5 := mload(0xa0)
4068
            m6 := mload(0xc0)
4069
            // Selector of `log(address,bool,string,bool)`.
4070
            mstore(0x00, 0x50ad461d)
4071
            mstore(0x20, p0)
4072
            mstore(0x40, p1)
4073
            mstore(0x60, 0x80)
4074
            mstore(0x80, p3)
4075
            writeString(0xa0, p2)
4076
        }
4077
        _sendLogPayload(0x1c, 0xc4);
4078
        /// @solidity memory-safe-assembly
4079
        assembly {
4080
            mstore(0x00, m0)
4081
            mstore(0x20, m1)
4082
            mstore(0x40, m2)
4083
            mstore(0x60, m3)
4084
            mstore(0x80, m4)
4085
            mstore(0xa0, m5)
4086
            mstore(0xc0, m6)
4087
        }
4088
    }
4089

                            
                        
4090
    function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure {
4091
        bytes32 m0;
4092
        bytes32 m1;
4093
        bytes32 m2;
4094
        bytes32 m3;
4095
        bytes32 m4;
4096
        bytes32 m5;
4097
        bytes32 m6;
4098
        /// @solidity memory-safe-assembly
4099
        assembly {
4100
            function writeString(pos, w) {
4101
                let length := 0
4102
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4103
                mstore(pos, length)
4104
                let shift := sub(256, shl(3, length))
4105
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4106
            }
4107
            m0 := mload(0x00)
4108
            m1 := mload(0x20)
4109
            m2 := mload(0x40)
4110
            m3 := mload(0x60)
4111
            m4 := mload(0x80)
4112
            m5 := mload(0xa0)
4113
            m6 := mload(0xc0)
4114
            // Selector of `log(address,bool,string,uint256)`.
4115
            mstore(0x00, 0x80e6a20b)
4116
            mstore(0x20, p0)
4117
            mstore(0x40, p1)
4118
            mstore(0x60, 0x80)
4119
            mstore(0x80, p3)
4120
            writeString(0xa0, p2)
4121
        }
4122
        _sendLogPayload(0x1c, 0xc4);
4123
        /// @solidity memory-safe-assembly
4124
        assembly {
4125
            mstore(0x00, m0)
4126
            mstore(0x20, m1)
4127
            mstore(0x40, m2)
4128
            mstore(0x60, m3)
4129
            mstore(0x80, m4)
4130
            mstore(0xa0, m5)
4131
            mstore(0xc0, m6)
4132
        }
4133
    }
4134

                            
                        
4135
    function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
4136
        bytes32 m0;
4137
        bytes32 m1;
4138
        bytes32 m2;
4139
        bytes32 m3;
4140
        bytes32 m4;
4141
        bytes32 m5;
4142
        bytes32 m6;
4143
        bytes32 m7;
4144
        bytes32 m8;
4145
        /// @solidity memory-safe-assembly
4146
        assembly {
4147
            function writeString(pos, w) {
4148
                let length := 0
4149
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4150
                mstore(pos, length)
4151
                let shift := sub(256, shl(3, length))
4152
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4153
            }
4154
            m0 := mload(0x00)
4155
            m1 := mload(0x20)
4156
            m2 := mload(0x40)
4157
            m3 := mload(0x60)
4158
            m4 := mload(0x80)
4159
            m5 := mload(0xa0)
4160
            m6 := mload(0xc0)
4161
            m7 := mload(0xe0)
4162
            m8 := mload(0x100)
4163
            // Selector of `log(address,bool,string,string)`.
4164
            mstore(0x00, 0x475c5c33)
4165
            mstore(0x20, p0)
4166
            mstore(0x40, p1)
4167
            mstore(0x60, 0x80)
4168
            mstore(0x80, 0xc0)
4169
            writeString(0xa0, p2)
4170
            writeString(0xe0, p3)
4171
        }
4172
        _sendLogPayload(0x1c, 0x104);
4173
        /// @solidity memory-safe-assembly
4174
        assembly {
4175
            mstore(0x00, m0)
4176
            mstore(0x20, m1)
4177
            mstore(0x40, m2)
4178
            mstore(0x60, m3)
4179
            mstore(0x80, m4)
4180
            mstore(0xa0, m5)
4181
            mstore(0xc0, m6)
4182
            mstore(0xe0, m7)
4183
            mstore(0x100, m8)
4184
        }
4185
    }
4186

                            
                        
4187
    function log(address p0, uint256 p1, address p2, address p3) internal pure {
4188
        bytes32 m0;
4189
        bytes32 m1;
4190
        bytes32 m2;
4191
        bytes32 m3;
4192
        bytes32 m4;
4193
        /// @solidity memory-safe-assembly
4194
        assembly {
4195
            m0 := mload(0x00)
4196
            m1 := mload(0x20)
4197
            m2 := mload(0x40)
4198
            m3 := mload(0x60)
4199
            m4 := mload(0x80)
4200
            // Selector of `log(address,uint256,address,address)`.
4201
            mstore(0x00, 0x478d1c62)
4202
            mstore(0x20, p0)
4203
            mstore(0x40, p1)
4204
            mstore(0x60, p2)
4205
            mstore(0x80, p3)
4206
        }
4207
        _sendLogPayload(0x1c, 0x84);
4208
        /// @solidity memory-safe-assembly
4209
        assembly {
4210
            mstore(0x00, m0)
4211
            mstore(0x20, m1)
4212
            mstore(0x40, m2)
4213
            mstore(0x60, m3)
4214
            mstore(0x80, m4)
4215
        }
4216
    }
4217

                            
                        
4218
    function log(address p0, uint256 p1, address p2, bool p3) internal pure {
4219
        bytes32 m0;
4220
        bytes32 m1;
4221
        bytes32 m2;
4222
        bytes32 m3;
4223
        bytes32 m4;
4224
        /// @solidity memory-safe-assembly
4225
        assembly {
4226
            m0 := mload(0x00)
4227
            m1 := mload(0x20)
4228
            m2 := mload(0x40)
4229
            m3 := mload(0x60)
4230
            m4 := mload(0x80)
4231
            // Selector of `log(address,uint256,address,bool)`.
4232
            mstore(0x00, 0xa1bcc9b3)
4233
            mstore(0x20, p0)
4234
            mstore(0x40, p1)
4235
            mstore(0x60, p2)
4236
            mstore(0x80, p3)
4237
        }
4238
        _sendLogPayload(0x1c, 0x84);
4239
        /// @solidity memory-safe-assembly
4240
        assembly {
4241
            mstore(0x00, m0)
4242
            mstore(0x20, m1)
4243
            mstore(0x40, m2)
4244
            mstore(0x60, m3)
4245
            mstore(0x80, m4)
4246
        }
4247
    }
4248

                            
                        
4249
    function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
4250
        bytes32 m0;
4251
        bytes32 m1;
4252
        bytes32 m2;
4253
        bytes32 m3;
4254
        bytes32 m4;
4255
        /// @solidity memory-safe-assembly
4256
        assembly {
4257
            m0 := mload(0x00)
4258
            m1 := mload(0x20)
4259
            m2 := mload(0x40)
4260
            m3 := mload(0x60)
4261
            m4 := mload(0x80)
4262
            // Selector of `log(address,uint256,address,uint256)`.
4263
            mstore(0x00, 0x100f650e)
4264
            mstore(0x20, p0)
4265
            mstore(0x40, p1)
4266
            mstore(0x60, p2)
4267
            mstore(0x80, p3)
4268
        }
4269
        _sendLogPayload(0x1c, 0x84);
4270
        /// @solidity memory-safe-assembly
4271
        assembly {
4272
            mstore(0x00, m0)
4273
            mstore(0x20, m1)
4274
            mstore(0x40, m2)
4275
            mstore(0x60, m3)
4276
            mstore(0x80, m4)
4277
        }
4278
    }
4279

                            
                        
4280
    function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure {
4281
        bytes32 m0;
4282
        bytes32 m1;
4283
        bytes32 m2;
4284
        bytes32 m3;
4285
        bytes32 m4;
4286
        bytes32 m5;
4287
        bytes32 m6;
4288
        /// @solidity memory-safe-assembly
4289
        assembly {
4290
            function writeString(pos, w) {
4291
                let length := 0
4292
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4293
                mstore(pos, length)
4294
                let shift := sub(256, shl(3, length))
4295
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4296
            }
4297
            m0 := mload(0x00)
4298
            m1 := mload(0x20)
4299
            m2 := mload(0x40)
4300
            m3 := mload(0x60)
4301
            m4 := mload(0x80)
4302
            m5 := mload(0xa0)
4303
            m6 := mload(0xc0)
4304
            // Selector of `log(address,uint256,address,string)`.
4305
            mstore(0x00, 0x1da986ea)
4306
            mstore(0x20, p0)
4307
            mstore(0x40, p1)
4308
            mstore(0x60, p2)
4309
            mstore(0x80, 0x80)
4310
            writeString(0xa0, p3)
4311
        }
4312
        _sendLogPayload(0x1c, 0xc4);
4313
        /// @solidity memory-safe-assembly
4314
        assembly {
4315
            mstore(0x00, m0)
4316
            mstore(0x20, m1)
4317
            mstore(0x40, m2)
4318
            mstore(0x60, m3)
4319
            mstore(0x80, m4)
4320
            mstore(0xa0, m5)
4321
            mstore(0xc0, m6)
4322
        }
4323
    }
4324

                            
                        
4325
    function log(address p0, uint256 p1, bool p2, address p3) internal pure {
4326
        bytes32 m0;
4327
        bytes32 m1;
4328
        bytes32 m2;
4329
        bytes32 m3;
4330
        bytes32 m4;
4331
        /// @solidity memory-safe-assembly
4332
        assembly {
4333
            m0 := mload(0x00)
4334
            m1 := mload(0x20)
4335
            m2 := mload(0x40)
4336
            m3 := mload(0x60)
4337
            m4 := mload(0x80)
4338
            // Selector of `log(address,uint256,bool,address)`.
4339
            mstore(0x00, 0xa31bfdcc)
4340
            mstore(0x20, p0)
4341
            mstore(0x40, p1)
4342
            mstore(0x60, p2)
4343
            mstore(0x80, p3)
4344
        }
4345
        _sendLogPayload(0x1c, 0x84);
4346
        /// @solidity memory-safe-assembly
4347
        assembly {
4348
            mstore(0x00, m0)
4349
            mstore(0x20, m1)
4350
            mstore(0x40, m2)
4351
            mstore(0x60, m3)
4352
            mstore(0x80, m4)
4353
        }
4354
    }
4355

                            
                        
4356
    function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
4357
        bytes32 m0;
4358
        bytes32 m1;
4359
        bytes32 m2;
4360
        bytes32 m3;
4361
        bytes32 m4;
4362
        /// @solidity memory-safe-assembly
4363
        assembly {
4364
            m0 := mload(0x00)
4365
            m1 := mload(0x20)
4366
            m2 := mload(0x40)
4367
            m3 := mload(0x60)
4368
            m4 := mload(0x80)
4369
            // Selector of `log(address,uint256,bool,bool)`.
4370
            mstore(0x00, 0x3bf5e537)
4371
            mstore(0x20, p0)
4372
            mstore(0x40, p1)
4373
            mstore(0x60, p2)
4374
            mstore(0x80, p3)
4375
        }
4376
        _sendLogPayload(0x1c, 0x84);
4377
        /// @solidity memory-safe-assembly
4378
        assembly {
4379
            mstore(0x00, m0)
4380
            mstore(0x20, m1)
4381
            mstore(0x40, m2)
4382
            mstore(0x60, m3)
4383
            mstore(0x80, m4)
4384
        }
4385
    }
4386

                            
                        
4387
    function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
4388
        bytes32 m0;
4389
        bytes32 m1;
4390
        bytes32 m2;
4391
        bytes32 m3;
4392
        bytes32 m4;
4393
        /// @solidity memory-safe-assembly
4394
        assembly {
4395
            m0 := mload(0x00)
4396
            m1 := mload(0x20)
4397
            m2 := mload(0x40)
4398
            m3 := mload(0x60)
4399
            m4 := mload(0x80)
4400
            // Selector of `log(address,uint256,bool,uint256)`.
4401
            mstore(0x00, 0x22f6b999)
4402
            mstore(0x20, p0)
4403
            mstore(0x40, p1)
4404
            mstore(0x60, p2)
4405
            mstore(0x80, p3)
4406
        }
4407
        _sendLogPayload(0x1c, 0x84);
4408
        /// @solidity memory-safe-assembly
4409
        assembly {
4410
            mstore(0x00, m0)
4411
            mstore(0x20, m1)
4412
            mstore(0x40, m2)
4413
            mstore(0x60, m3)
4414
            mstore(0x80, m4)
4415
        }
4416
    }
4417

                            
                        
4418
    function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure {
4419
        bytes32 m0;
4420
        bytes32 m1;
4421
        bytes32 m2;
4422
        bytes32 m3;
4423
        bytes32 m4;
4424
        bytes32 m5;
4425
        bytes32 m6;
4426
        /// @solidity memory-safe-assembly
4427
        assembly {
4428
            function writeString(pos, w) {
4429
                let length := 0
4430
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4431
                mstore(pos, length)
4432
                let shift := sub(256, shl(3, length))
4433
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4434
            }
4435
            m0 := mload(0x00)
4436
            m1 := mload(0x20)
4437
            m2 := mload(0x40)
4438
            m3 := mload(0x60)
4439
            m4 := mload(0x80)
4440
            m5 := mload(0xa0)
4441
            m6 := mload(0xc0)
4442
            // Selector of `log(address,uint256,bool,string)`.
4443
            mstore(0x00, 0xc5ad85f9)
4444
            mstore(0x20, p0)
4445
            mstore(0x40, p1)
4446
            mstore(0x60, p2)
4447
            mstore(0x80, 0x80)
4448
            writeString(0xa0, p3)
4449
        }
4450
        _sendLogPayload(0x1c, 0xc4);
4451
        /// @solidity memory-safe-assembly
4452
        assembly {
4453
            mstore(0x00, m0)
4454
            mstore(0x20, m1)
4455
            mstore(0x40, m2)
4456
            mstore(0x60, m3)
4457
            mstore(0x80, m4)
4458
            mstore(0xa0, m5)
4459
            mstore(0xc0, m6)
4460
        }
4461
    }
4462

                            
                        
4463
    function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
4464
        bytes32 m0;
4465
        bytes32 m1;
4466
        bytes32 m2;
4467
        bytes32 m3;
4468
        bytes32 m4;
4469
        /// @solidity memory-safe-assembly
4470
        assembly {
4471
            m0 := mload(0x00)
4472
            m1 := mload(0x20)
4473
            m2 := mload(0x40)
4474
            m3 := mload(0x60)
4475
            m4 := mload(0x80)
4476
            // Selector of `log(address,uint256,uint256,address)`.
4477
            mstore(0x00, 0x20e3984d)
4478
            mstore(0x20, p0)
4479
            mstore(0x40, p1)
4480
            mstore(0x60, p2)
4481
            mstore(0x80, p3)
4482
        }
4483
        _sendLogPayload(0x1c, 0x84);
4484
        /// @solidity memory-safe-assembly
4485
        assembly {
4486
            mstore(0x00, m0)
4487
            mstore(0x20, m1)
4488
            mstore(0x40, m2)
4489
            mstore(0x60, m3)
4490
            mstore(0x80, m4)
4491
        }
4492
    }
4493

                            
                        
4494
    function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
4495
        bytes32 m0;
4496
        bytes32 m1;
4497
        bytes32 m2;
4498
        bytes32 m3;
4499
        bytes32 m4;
4500
        /// @solidity memory-safe-assembly
4501
        assembly {
4502
            m0 := mload(0x00)
4503
            m1 := mload(0x20)
4504
            m2 := mload(0x40)
4505
            m3 := mload(0x60)
4506
            m4 := mload(0x80)
4507
            // Selector of `log(address,uint256,uint256,bool)`.
4508
            mstore(0x00, 0x66f1bc67)
4509
            mstore(0x20, p0)
4510
            mstore(0x40, p1)
4511
            mstore(0x60, p2)
4512
            mstore(0x80, p3)
4513
        }
4514
        _sendLogPayload(0x1c, 0x84);
4515
        /// @solidity memory-safe-assembly
4516
        assembly {
4517
            mstore(0x00, m0)
4518
            mstore(0x20, m1)
4519
            mstore(0x40, m2)
4520
            mstore(0x60, m3)
4521
            mstore(0x80, m4)
4522
        }
4523
    }
4524

                            
                        
4525
    function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
4526
        bytes32 m0;
4527
        bytes32 m1;
4528
        bytes32 m2;
4529
        bytes32 m3;
4530
        bytes32 m4;
4531
        /// @solidity memory-safe-assembly
4532
        assembly {
4533
            m0 := mload(0x00)
4534
            m1 := mload(0x20)
4535
            m2 := mload(0x40)
4536
            m3 := mload(0x60)
4537
            m4 := mload(0x80)
4538
            // Selector of `log(address,uint256,uint256,uint256)`.
4539
            mstore(0x00, 0x34f0e636)
4540
            mstore(0x20, p0)
4541
            mstore(0x40, p1)
4542
            mstore(0x60, p2)
4543
            mstore(0x80, p3)
4544
        }
4545
        _sendLogPayload(0x1c, 0x84);
4546
        /// @solidity memory-safe-assembly
4547
        assembly {
4548
            mstore(0x00, m0)
4549
            mstore(0x20, m1)
4550
            mstore(0x40, m2)
4551
            mstore(0x60, m3)
4552
            mstore(0x80, m4)
4553
        }
4554
    }
4555

                            
                        
4556
    function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
4557
        bytes32 m0;
4558
        bytes32 m1;
4559
        bytes32 m2;
4560
        bytes32 m3;
4561
        bytes32 m4;
4562
        bytes32 m5;
4563
        bytes32 m6;
4564
        /// @solidity memory-safe-assembly
4565
        assembly {
4566
            function writeString(pos, w) {
4567
                let length := 0
4568
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4569
                mstore(pos, length)
4570
                let shift := sub(256, shl(3, length))
4571
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4572
            }
4573
            m0 := mload(0x00)
4574
            m1 := mload(0x20)
4575
            m2 := mload(0x40)
4576
            m3 := mload(0x60)
4577
            m4 := mload(0x80)
4578
            m5 := mload(0xa0)
4579
            m6 := mload(0xc0)
4580
            // Selector of `log(address,uint256,uint256,string)`.
4581
            mstore(0x00, 0x4a28c017)
4582
            mstore(0x20, p0)
4583
            mstore(0x40, p1)
4584
            mstore(0x60, p2)
4585
            mstore(0x80, 0x80)
4586
            writeString(0xa0, p3)
4587
        }
4588
        _sendLogPayload(0x1c, 0xc4);
4589
        /// @solidity memory-safe-assembly
4590
        assembly {
4591
            mstore(0x00, m0)
4592
            mstore(0x20, m1)
4593
            mstore(0x40, m2)
4594
            mstore(0x60, m3)
4595
            mstore(0x80, m4)
4596
            mstore(0xa0, m5)
4597
            mstore(0xc0, m6)
4598
        }
4599
    }
4600

                            
                        
4601
    function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure {
4602
        bytes32 m0;
4603
        bytes32 m1;
4604
        bytes32 m2;
4605
        bytes32 m3;
4606
        bytes32 m4;
4607
        bytes32 m5;
4608
        bytes32 m6;
4609
        /// @solidity memory-safe-assembly
4610
        assembly {
4611
            function writeString(pos, w) {
4612
                let length := 0
4613
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4614
                mstore(pos, length)
4615
                let shift := sub(256, shl(3, length))
4616
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4617
            }
4618
            m0 := mload(0x00)
4619
            m1 := mload(0x20)
4620
            m2 := mload(0x40)
4621
            m3 := mload(0x60)
4622
            m4 := mload(0x80)
4623
            m5 := mload(0xa0)
4624
            m6 := mload(0xc0)
4625
            // Selector of `log(address,uint256,string,address)`.
4626
            mstore(0x00, 0x5c430d47)
4627
            mstore(0x20, p0)
4628
            mstore(0x40, p1)
4629
            mstore(0x60, 0x80)
4630
            mstore(0x80, p3)
4631
            writeString(0xa0, p2)
4632
        }
4633
        _sendLogPayload(0x1c, 0xc4);
4634
        /// @solidity memory-safe-assembly
4635
        assembly {
4636
            mstore(0x00, m0)
4637
            mstore(0x20, m1)
4638
            mstore(0x40, m2)
4639
            mstore(0x60, m3)
4640
            mstore(0x80, m4)
4641
            mstore(0xa0, m5)
4642
            mstore(0xc0, m6)
4643
        }
4644
    }
4645

                            
                        
4646
    function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure {
4647
        bytes32 m0;
4648
        bytes32 m1;
4649
        bytes32 m2;
4650
        bytes32 m3;
4651
        bytes32 m4;
4652
        bytes32 m5;
4653
        bytes32 m6;
4654
        /// @solidity memory-safe-assembly
4655
        assembly {
4656
            function writeString(pos, w) {
4657
                let length := 0
4658
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4659
                mstore(pos, length)
4660
                let shift := sub(256, shl(3, length))
4661
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4662
            }
4663
            m0 := mload(0x00)
4664
            m1 := mload(0x20)
4665
            m2 := mload(0x40)
4666
            m3 := mload(0x60)
4667
            m4 := mload(0x80)
4668
            m5 := mload(0xa0)
4669
            m6 := mload(0xc0)
4670
            // Selector of `log(address,uint256,string,bool)`.
4671
            mstore(0x00, 0xcf18105c)
4672
            mstore(0x20, p0)
4673
            mstore(0x40, p1)
4674
            mstore(0x60, 0x80)
4675
            mstore(0x80, p3)
4676
            writeString(0xa0, p2)
4677
        }
4678
        _sendLogPayload(0x1c, 0xc4);
4679
        /// @solidity memory-safe-assembly
4680
        assembly {
4681
            mstore(0x00, m0)
4682
            mstore(0x20, m1)
4683
            mstore(0x40, m2)
4684
            mstore(0x60, m3)
4685
            mstore(0x80, m4)
4686
            mstore(0xa0, m5)
4687
            mstore(0xc0, m6)
4688
        }
4689
    }
4690

                            
                        
4691
    function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
4692
        bytes32 m0;
4693
        bytes32 m1;
4694
        bytes32 m2;
4695
        bytes32 m3;
4696
        bytes32 m4;
4697
        bytes32 m5;
4698
        bytes32 m6;
4699
        /// @solidity memory-safe-assembly
4700
        assembly {
4701
            function writeString(pos, w) {
4702
                let length := 0
4703
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4704
                mstore(pos, length)
4705
                let shift := sub(256, shl(3, length))
4706
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4707
            }
4708
            m0 := mload(0x00)
4709
            m1 := mload(0x20)
4710
            m2 := mload(0x40)
4711
            m3 := mload(0x60)
4712
            m4 := mload(0x80)
4713
            m5 := mload(0xa0)
4714
            m6 := mload(0xc0)
4715
            // Selector of `log(address,uint256,string,uint256)`.
4716
            mstore(0x00, 0xbf01f891)
4717
            mstore(0x20, p0)
4718
            mstore(0x40, p1)
4719
            mstore(0x60, 0x80)
4720
            mstore(0x80, p3)
4721
            writeString(0xa0, p2)
4722
        }
4723
        _sendLogPayload(0x1c, 0xc4);
4724
        /// @solidity memory-safe-assembly
4725
        assembly {
4726
            mstore(0x00, m0)
4727
            mstore(0x20, m1)
4728
            mstore(0x40, m2)
4729
            mstore(0x60, m3)
4730
            mstore(0x80, m4)
4731
            mstore(0xa0, m5)
4732
            mstore(0xc0, m6)
4733
        }
4734
    }
4735

                            
                        
4736
    function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
4737
        bytes32 m0;
4738
        bytes32 m1;
4739
        bytes32 m2;
4740
        bytes32 m3;
4741
        bytes32 m4;
4742
        bytes32 m5;
4743
        bytes32 m6;
4744
        bytes32 m7;
4745
        bytes32 m8;
4746
        /// @solidity memory-safe-assembly
4747
        assembly {
4748
            function writeString(pos, w) {
4749
                let length := 0
4750
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4751
                mstore(pos, length)
4752
                let shift := sub(256, shl(3, length))
4753
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4754
            }
4755
            m0 := mload(0x00)
4756
            m1 := mload(0x20)
4757
            m2 := mload(0x40)
4758
            m3 := mload(0x60)
4759
            m4 := mload(0x80)
4760
            m5 := mload(0xa0)
4761
            m6 := mload(0xc0)
4762
            m7 := mload(0xe0)
4763
            m8 := mload(0x100)
4764
            // Selector of `log(address,uint256,string,string)`.
4765
            mstore(0x00, 0x88a8c406)
4766
            mstore(0x20, p0)
4767
            mstore(0x40, p1)
4768
            mstore(0x60, 0x80)
4769
            mstore(0x80, 0xc0)
4770
            writeString(0xa0, p2)
4771
            writeString(0xe0, p3)
4772
        }
4773
        _sendLogPayload(0x1c, 0x104);
4774
        /// @solidity memory-safe-assembly
4775
        assembly {
4776
            mstore(0x00, m0)
4777
            mstore(0x20, m1)
4778
            mstore(0x40, m2)
4779
            mstore(0x60, m3)
4780
            mstore(0x80, m4)
4781
            mstore(0xa0, m5)
4782
            mstore(0xc0, m6)
4783
            mstore(0xe0, m7)
4784
            mstore(0x100, m8)
4785
        }
4786
    }
4787

                            
                        
4788
    function log(address p0, bytes32 p1, address p2, address p3) internal pure {
4789
        bytes32 m0;
4790
        bytes32 m1;
4791
        bytes32 m2;
4792
        bytes32 m3;
4793
        bytes32 m4;
4794
        bytes32 m5;
4795
        bytes32 m6;
4796
        /// @solidity memory-safe-assembly
4797
        assembly {
4798
            function writeString(pos, w) {
4799
                let length := 0
4800
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4801
                mstore(pos, length)
4802
                let shift := sub(256, shl(3, length))
4803
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4804
            }
4805
            m0 := mload(0x00)
4806
            m1 := mload(0x20)
4807
            m2 := mload(0x40)
4808
            m3 := mload(0x60)
4809
            m4 := mload(0x80)
4810
            m5 := mload(0xa0)
4811
            m6 := mload(0xc0)
4812
            // Selector of `log(address,string,address,address)`.
4813
            mstore(0x00, 0x0d36fa20)
4814
            mstore(0x20, p0)
4815
            mstore(0x40, 0x80)
4816
            mstore(0x60, p2)
4817
            mstore(0x80, p3)
4818
            writeString(0xa0, p1)
4819
        }
4820
        _sendLogPayload(0x1c, 0xc4);
4821
        /// @solidity memory-safe-assembly
4822
        assembly {
4823
            mstore(0x00, m0)
4824
            mstore(0x20, m1)
4825
            mstore(0x40, m2)
4826
            mstore(0x60, m3)
4827
            mstore(0x80, m4)
4828
            mstore(0xa0, m5)
4829
            mstore(0xc0, m6)
4830
        }
4831
    }
4832

                            
                        
4833
    function log(address p0, bytes32 p1, address p2, bool p3) internal pure {
4834
        bytes32 m0;
4835
        bytes32 m1;
4836
        bytes32 m2;
4837
        bytes32 m3;
4838
        bytes32 m4;
4839
        bytes32 m5;
4840
        bytes32 m6;
4841
        /// @solidity memory-safe-assembly
4842
        assembly {
4843
            function writeString(pos, w) {
4844
                let length := 0
4845
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4846
                mstore(pos, length)
4847
                let shift := sub(256, shl(3, length))
4848
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4849
            }
4850
            m0 := mload(0x00)
4851
            m1 := mload(0x20)
4852
            m2 := mload(0x40)
4853
            m3 := mload(0x60)
4854
            m4 := mload(0x80)
4855
            m5 := mload(0xa0)
4856
            m6 := mload(0xc0)
4857
            // Selector of `log(address,string,address,bool)`.
4858
            mstore(0x00, 0x0df12b76)
4859
            mstore(0x20, p0)
4860
            mstore(0x40, 0x80)
4861
            mstore(0x60, p2)
4862
            mstore(0x80, p3)
4863
            writeString(0xa0, p1)
4864
        }
4865
        _sendLogPayload(0x1c, 0xc4);
4866
        /// @solidity memory-safe-assembly
4867
        assembly {
4868
            mstore(0x00, m0)
4869
            mstore(0x20, m1)
4870
            mstore(0x40, m2)
4871
            mstore(0x60, m3)
4872
            mstore(0x80, m4)
4873
            mstore(0xa0, m5)
4874
            mstore(0xc0, m6)
4875
        }
4876
    }
4877

                            
                        
4878
    function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure {
4879
        bytes32 m0;
4880
        bytes32 m1;
4881
        bytes32 m2;
4882
        bytes32 m3;
4883
        bytes32 m4;
4884
        bytes32 m5;
4885
        bytes32 m6;
4886
        /// @solidity memory-safe-assembly
4887
        assembly {
4888
            function writeString(pos, w) {
4889
                let length := 0
4890
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4891
                mstore(pos, length)
4892
                let shift := sub(256, shl(3, length))
4893
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4894
            }
4895
            m0 := mload(0x00)
4896
            m1 := mload(0x20)
4897
            m2 := mload(0x40)
4898
            m3 := mload(0x60)
4899
            m4 := mload(0x80)
4900
            m5 := mload(0xa0)
4901
            m6 := mload(0xc0)
4902
            // Selector of `log(address,string,address,uint256)`.
4903
            mstore(0x00, 0x457fe3cf)
4904
            mstore(0x20, p0)
4905
            mstore(0x40, 0x80)
4906
            mstore(0x60, p2)
4907
            mstore(0x80, p3)
4908
            writeString(0xa0, p1)
4909
        }
4910
        _sendLogPayload(0x1c, 0xc4);
4911
        /// @solidity memory-safe-assembly
4912
        assembly {
4913
            mstore(0x00, m0)
4914
            mstore(0x20, m1)
4915
            mstore(0x40, m2)
4916
            mstore(0x60, m3)
4917
            mstore(0x80, m4)
4918
            mstore(0xa0, m5)
4919
            mstore(0xc0, m6)
4920
        }
4921
    }
4922

                            
                        
4923
    function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure {
4924
        bytes32 m0;
4925
        bytes32 m1;
4926
        bytes32 m2;
4927
        bytes32 m3;
4928
        bytes32 m4;
4929
        bytes32 m5;
4930
        bytes32 m6;
4931
        bytes32 m7;
4932
        bytes32 m8;
4933
        /// @solidity memory-safe-assembly
4934
        assembly {
4935
            function writeString(pos, w) {
4936
                let length := 0
4937
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4938
                mstore(pos, length)
4939
                let shift := sub(256, shl(3, length))
4940
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4941
            }
4942
            m0 := mload(0x00)
4943
            m1 := mload(0x20)
4944
            m2 := mload(0x40)
4945
            m3 := mload(0x60)
4946
            m4 := mload(0x80)
4947
            m5 := mload(0xa0)
4948
            m6 := mload(0xc0)
4949
            m7 := mload(0xe0)
4950
            m8 := mload(0x100)
4951
            // Selector of `log(address,string,address,string)`.
4952
            mstore(0x00, 0xf7e36245)
4953
            mstore(0x20, p0)
4954
            mstore(0x40, 0x80)
4955
            mstore(0x60, p2)
4956
            mstore(0x80, 0xc0)
4957
            writeString(0xa0, p1)
4958
            writeString(0xe0, p3)
4959
        }
4960
        _sendLogPayload(0x1c, 0x104);
4961
        /// @solidity memory-safe-assembly
4962
        assembly {
4963
            mstore(0x00, m0)
4964
            mstore(0x20, m1)
4965
            mstore(0x40, m2)
4966
            mstore(0x60, m3)
4967
            mstore(0x80, m4)
4968
            mstore(0xa0, m5)
4969
            mstore(0xc0, m6)
4970
            mstore(0xe0, m7)
4971
            mstore(0x100, m8)
4972
        }
4973
    }
4974

                            
                        
4975
    function log(address p0, bytes32 p1, bool p2, address p3) internal pure {
4976
        bytes32 m0;
4977
        bytes32 m1;
4978
        bytes32 m2;
4979
        bytes32 m3;
4980
        bytes32 m4;
4981
        bytes32 m5;
4982
        bytes32 m6;
4983
        /// @solidity memory-safe-assembly
4984
        assembly {
4985
            function writeString(pos, w) {
4986
                let length := 0
4987
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
4988
                mstore(pos, length)
4989
                let shift := sub(256, shl(3, length))
4990
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
4991
            }
4992
            m0 := mload(0x00)
4993
            m1 := mload(0x20)
4994
            m2 := mload(0x40)
4995
            m3 := mload(0x60)
4996
            m4 := mload(0x80)
4997
            m5 := mload(0xa0)
4998
            m6 := mload(0xc0)
4999
            // Selector of `log(address,string,bool,address)`.
5000
            mstore(0x00, 0x205871c2)
5001
            mstore(0x20, p0)
5002
            mstore(0x40, 0x80)
5003
            mstore(0x60, p2)
5004
            mstore(0x80, p3)
5005
            writeString(0xa0, p1)
5006
        }
5007
        _sendLogPayload(0x1c, 0xc4);
5008
        /// @solidity memory-safe-assembly
5009
        assembly {
5010
            mstore(0x00, m0)
5011
            mstore(0x20, m1)
5012
            mstore(0x40, m2)
5013
            mstore(0x60, m3)
5014
            mstore(0x80, m4)
5015
            mstore(0xa0, m5)
5016
            mstore(0xc0, m6)
5017
        }
5018
    }
5019

                            
                        
5020
    function log(address p0, bytes32 p1, bool p2, bool p3) internal pure {
5021
        bytes32 m0;
5022
        bytes32 m1;
5023
        bytes32 m2;
5024
        bytes32 m3;
5025
        bytes32 m4;
5026
        bytes32 m5;
5027
        bytes32 m6;
5028
        /// @solidity memory-safe-assembly
5029
        assembly {
5030
            function writeString(pos, w) {
5031
                let length := 0
5032
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5033
                mstore(pos, length)
5034
                let shift := sub(256, shl(3, length))
5035
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5036
            }
5037
            m0 := mload(0x00)
5038
            m1 := mload(0x20)
5039
            m2 := mload(0x40)
5040
            m3 := mload(0x60)
5041
            m4 := mload(0x80)
5042
            m5 := mload(0xa0)
5043
            m6 := mload(0xc0)
5044
            // Selector of `log(address,string,bool,bool)`.
5045
            mstore(0x00, 0x5f1d5c9f)
5046
            mstore(0x20, p0)
5047
            mstore(0x40, 0x80)
5048
            mstore(0x60, p2)
5049
            mstore(0x80, p3)
5050
            writeString(0xa0, p1)
5051
        }
5052
        _sendLogPayload(0x1c, 0xc4);
5053
        /// @solidity memory-safe-assembly
5054
        assembly {
5055
            mstore(0x00, m0)
5056
            mstore(0x20, m1)
5057
            mstore(0x40, m2)
5058
            mstore(0x60, m3)
5059
            mstore(0x80, m4)
5060
            mstore(0xa0, m5)
5061
            mstore(0xc0, m6)
5062
        }
5063
    }
5064

                            
                        
5065
    function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure {
5066
        bytes32 m0;
5067
        bytes32 m1;
5068
        bytes32 m2;
5069
        bytes32 m3;
5070
        bytes32 m4;
5071
        bytes32 m5;
5072
        bytes32 m6;
5073
        /// @solidity memory-safe-assembly
5074
        assembly {
5075
            function writeString(pos, w) {
5076
                let length := 0
5077
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5078
                mstore(pos, length)
5079
                let shift := sub(256, shl(3, length))
5080
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5081
            }
5082
            m0 := mload(0x00)
5083
            m1 := mload(0x20)
5084
            m2 := mload(0x40)
5085
            m3 := mload(0x60)
5086
            m4 := mload(0x80)
5087
            m5 := mload(0xa0)
5088
            m6 := mload(0xc0)
5089
            // Selector of `log(address,string,bool,uint256)`.
5090
            mstore(0x00, 0x515e38b6)
5091
            mstore(0x20, p0)
5092
            mstore(0x40, 0x80)
5093
            mstore(0x60, p2)
5094
            mstore(0x80, p3)
5095
            writeString(0xa0, p1)
5096
        }
5097
        _sendLogPayload(0x1c, 0xc4);
5098
        /// @solidity memory-safe-assembly
5099
        assembly {
5100
            mstore(0x00, m0)
5101
            mstore(0x20, m1)
5102
            mstore(0x40, m2)
5103
            mstore(0x60, m3)
5104
            mstore(0x80, m4)
5105
            mstore(0xa0, m5)
5106
            mstore(0xc0, m6)
5107
        }
5108
    }
5109

                            
                        
5110
    function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
5111
        bytes32 m0;
5112
        bytes32 m1;
5113
        bytes32 m2;
5114
        bytes32 m3;
5115
        bytes32 m4;
5116
        bytes32 m5;
5117
        bytes32 m6;
5118
        bytes32 m7;
5119
        bytes32 m8;
5120
        /// @solidity memory-safe-assembly
5121
        assembly {
5122
            function writeString(pos, w) {
5123
                let length := 0
5124
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5125
                mstore(pos, length)
5126
                let shift := sub(256, shl(3, length))
5127
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5128
            }
5129
            m0 := mload(0x00)
5130
            m1 := mload(0x20)
5131
            m2 := mload(0x40)
5132
            m3 := mload(0x60)
5133
            m4 := mload(0x80)
5134
            m5 := mload(0xa0)
5135
            m6 := mload(0xc0)
5136
            m7 := mload(0xe0)
5137
            m8 := mload(0x100)
5138
            // Selector of `log(address,string,bool,string)`.
5139
            mstore(0x00, 0xbc0b61fe)
5140
            mstore(0x20, p0)
5141
            mstore(0x40, 0x80)
5142
            mstore(0x60, p2)
5143
            mstore(0x80, 0xc0)
5144
            writeString(0xa0, p1)
5145
            writeString(0xe0, p3)
5146
        }
5147
        _sendLogPayload(0x1c, 0x104);
5148
        /// @solidity memory-safe-assembly
5149
        assembly {
5150
            mstore(0x00, m0)
5151
            mstore(0x20, m1)
5152
            mstore(0x40, m2)
5153
            mstore(0x60, m3)
5154
            mstore(0x80, m4)
5155
            mstore(0xa0, m5)
5156
            mstore(0xc0, m6)
5157
            mstore(0xe0, m7)
5158
            mstore(0x100, m8)
5159
        }
5160
    }
5161

                            
                        
5162
    function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure {
5163
        bytes32 m0;
5164
        bytes32 m1;
5165
        bytes32 m2;
5166
        bytes32 m3;
5167
        bytes32 m4;
5168
        bytes32 m5;
5169
        bytes32 m6;
5170
        /// @solidity memory-safe-assembly
5171
        assembly {
5172
            function writeString(pos, w) {
5173
                let length := 0
5174
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5175
                mstore(pos, length)
5176
                let shift := sub(256, shl(3, length))
5177
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5178
            }
5179
            m0 := mload(0x00)
5180
            m1 := mload(0x20)
5181
            m2 := mload(0x40)
5182
            m3 := mload(0x60)
5183
            m4 := mload(0x80)
5184
            m5 := mload(0xa0)
5185
            m6 := mload(0xc0)
5186
            // Selector of `log(address,string,uint256,address)`.
5187
            mstore(0x00, 0x63183678)
5188
            mstore(0x20, p0)
5189
            mstore(0x40, 0x80)
5190
            mstore(0x60, p2)
5191
            mstore(0x80, p3)
5192
            writeString(0xa0, p1)
5193
        }
5194
        _sendLogPayload(0x1c, 0xc4);
5195
        /// @solidity memory-safe-assembly
5196
        assembly {
5197
            mstore(0x00, m0)
5198
            mstore(0x20, m1)
5199
            mstore(0x40, m2)
5200
            mstore(0x60, m3)
5201
            mstore(0x80, m4)
5202
            mstore(0xa0, m5)
5203
            mstore(0xc0, m6)
5204
        }
5205
    }
5206

                            
                        
5207
    function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure {
5208
        bytes32 m0;
5209
        bytes32 m1;
5210
        bytes32 m2;
5211
        bytes32 m3;
5212
        bytes32 m4;
5213
        bytes32 m5;
5214
        bytes32 m6;
5215
        /// @solidity memory-safe-assembly
5216
        assembly {
5217
            function writeString(pos, w) {
5218
                let length := 0
5219
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5220
                mstore(pos, length)
5221
                let shift := sub(256, shl(3, length))
5222
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5223
            }
5224
            m0 := mload(0x00)
5225
            m1 := mload(0x20)
5226
            m2 := mload(0x40)
5227
            m3 := mload(0x60)
5228
            m4 := mload(0x80)
5229
            m5 := mload(0xa0)
5230
            m6 := mload(0xc0)
5231
            // Selector of `log(address,string,uint256,bool)`.
5232
            mstore(0x00, 0x0ef7e050)
5233
            mstore(0x20, p0)
5234
            mstore(0x40, 0x80)
5235
            mstore(0x60, p2)
5236
            mstore(0x80, p3)
5237
            writeString(0xa0, p1)
5238
        }
5239
        _sendLogPayload(0x1c, 0xc4);
5240
        /// @solidity memory-safe-assembly
5241
        assembly {
5242
            mstore(0x00, m0)
5243
            mstore(0x20, m1)
5244
            mstore(0x40, m2)
5245
            mstore(0x60, m3)
5246
            mstore(0x80, m4)
5247
            mstore(0xa0, m5)
5248
            mstore(0xc0, m6)
5249
        }
5250
    }
5251

                            
                        
5252
    function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
5253
        bytes32 m0;
5254
        bytes32 m1;
5255
        bytes32 m2;
5256
        bytes32 m3;
5257
        bytes32 m4;
5258
        bytes32 m5;
5259
        bytes32 m6;
5260
        /// @solidity memory-safe-assembly
5261
        assembly {
5262
            function writeString(pos, w) {
5263
                let length := 0
5264
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5265
                mstore(pos, length)
5266
                let shift := sub(256, shl(3, length))
5267
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5268
            }
5269
            m0 := mload(0x00)
5270
            m1 := mload(0x20)
5271
            m2 := mload(0x40)
5272
            m3 := mload(0x60)
5273
            m4 := mload(0x80)
5274
            m5 := mload(0xa0)
5275
            m6 := mload(0xc0)
5276
            // Selector of `log(address,string,uint256,uint256)`.
5277
            mstore(0x00, 0x1dc8e1b8)
5278
            mstore(0x20, p0)
5279
            mstore(0x40, 0x80)
5280
            mstore(0x60, p2)
5281
            mstore(0x80, p3)
5282
            writeString(0xa0, p1)
5283
        }
5284
        _sendLogPayload(0x1c, 0xc4);
5285
        /// @solidity memory-safe-assembly
5286
        assembly {
5287
            mstore(0x00, m0)
5288
            mstore(0x20, m1)
5289
            mstore(0x40, m2)
5290
            mstore(0x60, m3)
5291
            mstore(0x80, m4)
5292
            mstore(0xa0, m5)
5293
            mstore(0xc0, m6)
5294
        }
5295
    }
5296

                            
                        
5297
    function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
5298
        bytes32 m0;
5299
        bytes32 m1;
5300
        bytes32 m2;
5301
        bytes32 m3;
5302
        bytes32 m4;
5303
        bytes32 m5;
5304
        bytes32 m6;
5305
        bytes32 m7;
5306
        bytes32 m8;
5307
        /// @solidity memory-safe-assembly
5308
        assembly {
5309
            function writeString(pos, w) {
5310
                let length := 0
5311
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5312
                mstore(pos, length)
5313
                let shift := sub(256, shl(3, length))
5314
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5315
            }
5316
            m0 := mload(0x00)
5317
            m1 := mload(0x20)
5318
            m2 := mload(0x40)
5319
            m3 := mload(0x60)
5320
            m4 := mload(0x80)
5321
            m5 := mload(0xa0)
5322
            m6 := mload(0xc0)
5323
            m7 := mload(0xe0)
5324
            m8 := mload(0x100)
5325
            // Selector of `log(address,string,uint256,string)`.
5326
            mstore(0x00, 0x448830a8)
5327
            mstore(0x20, p0)
5328
            mstore(0x40, 0x80)
5329
            mstore(0x60, p2)
5330
            mstore(0x80, 0xc0)
5331
            writeString(0xa0, p1)
5332
            writeString(0xe0, p3)
5333
        }
5334
        _sendLogPayload(0x1c, 0x104);
5335
        /// @solidity memory-safe-assembly
5336
        assembly {
5337
            mstore(0x00, m0)
5338
            mstore(0x20, m1)
5339
            mstore(0x40, m2)
5340
            mstore(0x60, m3)
5341
            mstore(0x80, m4)
5342
            mstore(0xa0, m5)
5343
            mstore(0xc0, m6)
5344
            mstore(0xe0, m7)
5345
            mstore(0x100, m8)
5346
        }
5347
    }
5348

                            
                        
5349
    function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure {
5350
        bytes32 m0;
5351
        bytes32 m1;
5352
        bytes32 m2;
5353
        bytes32 m3;
5354
        bytes32 m4;
5355
        bytes32 m5;
5356
        bytes32 m6;
5357
        bytes32 m7;
5358
        bytes32 m8;
5359
        /// @solidity memory-safe-assembly
5360
        assembly {
5361
            function writeString(pos, w) {
5362
                let length := 0
5363
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5364
                mstore(pos, length)
5365
                let shift := sub(256, shl(3, length))
5366
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5367
            }
5368
            m0 := mload(0x00)
5369
            m1 := mload(0x20)
5370
            m2 := mload(0x40)
5371
            m3 := mload(0x60)
5372
            m4 := mload(0x80)
5373
            m5 := mload(0xa0)
5374
            m6 := mload(0xc0)
5375
            m7 := mload(0xe0)
5376
            m8 := mload(0x100)
5377
            // Selector of `log(address,string,string,address)`.
5378
            mstore(0x00, 0xa04e2f87)
5379
            mstore(0x20, p0)
5380
            mstore(0x40, 0x80)
5381
            mstore(0x60, 0xc0)
5382
            mstore(0x80, p3)
5383
            writeString(0xa0, p1)
5384
            writeString(0xe0, p2)
5385
        }
5386
        _sendLogPayload(0x1c, 0x104);
5387
        /// @solidity memory-safe-assembly
5388
        assembly {
5389
            mstore(0x00, m0)
5390
            mstore(0x20, m1)
5391
            mstore(0x40, m2)
5392
            mstore(0x60, m3)
5393
            mstore(0x80, m4)
5394
            mstore(0xa0, m5)
5395
            mstore(0xc0, m6)
5396
            mstore(0xe0, m7)
5397
            mstore(0x100, m8)
5398
        }
5399
    }
5400

                            
                        
5401
    function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
5402
        bytes32 m0;
5403
        bytes32 m1;
5404
        bytes32 m2;
5405
        bytes32 m3;
5406
        bytes32 m4;
5407
        bytes32 m5;
5408
        bytes32 m6;
5409
        bytes32 m7;
5410
        bytes32 m8;
5411
        /// @solidity memory-safe-assembly
5412
        assembly {
5413
            function writeString(pos, w) {
5414
                let length := 0
5415
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5416
                mstore(pos, length)
5417
                let shift := sub(256, shl(3, length))
5418
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5419
            }
5420
            m0 := mload(0x00)
5421
            m1 := mload(0x20)
5422
            m2 := mload(0x40)
5423
            m3 := mload(0x60)
5424
            m4 := mload(0x80)
5425
            m5 := mload(0xa0)
5426
            m6 := mload(0xc0)
5427
            m7 := mload(0xe0)
5428
            m8 := mload(0x100)
5429
            // Selector of `log(address,string,string,bool)`.
5430
            mstore(0x00, 0x35a5071f)
5431
            mstore(0x20, p0)
5432
            mstore(0x40, 0x80)
5433
            mstore(0x60, 0xc0)
5434
            mstore(0x80, p3)
5435
            writeString(0xa0, p1)
5436
            writeString(0xe0, p2)
5437
        }
5438
        _sendLogPayload(0x1c, 0x104);
5439
        /// @solidity memory-safe-assembly
5440
        assembly {
5441
            mstore(0x00, m0)
5442
            mstore(0x20, m1)
5443
            mstore(0x40, m2)
5444
            mstore(0x60, m3)
5445
            mstore(0x80, m4)
5446
            mstore(0xa0, m5)
5447
            mstore(0xc0, m6)
5448
            mstore(0xe0, m7)
5449
            mstore(0x100, m8)
5450
        }
5451
    }
5452

                            
                        
5453
    function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
5454
        bytes32 m0;
5455
        bytes32 m1;
5456
        bytes32 m2;
5457
        bytes32 m3;
5458
        bytes32 m4;
5459
        bytes32 m5;
5460
        bytes32 m6;
5461
        bytes32 m7;
5462
        bytes32 m8;
5463
        /// @solidity memory-safe-assembly
5464
        assembly {
5465
            function writeString(pos, w) {
5466
                let length := 0
5467
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5468
                mstore(pos, length)
5469
                let shift := sub(256, shl(3, length))
5470
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5471
            }
5472
            m0 := mload(0x00)
5473
            m1 := mload(0x20)
5474
            m2 := mload(0x40)
5475
            m3 := mload(0x60)
5476
            m4 := mload(0x80)
5477
            m5 := mload(0xa0)
5478
            m6 := mload(0xc0)
5479
            m7 := mload(0xe0)
5480
            m8 := mload(0x100)
5481
            // Selector of `log(address,string,string,uint256)`.
5482
            mstore(0x00, 0x159f8927)
5483
            mstore(0x20, p0)
5484
            mstore(0x40, 0x80)
5485
            mstore(0x60, 0xc0)
5486
            mstore(0x80, p3)
5487
            writeString(0xa0, p1)
5488
            writeString(0xe0, p2)
5489
        }
5490
        _sendLogPayload(0x1c, 0x104);
5491
        /// @solidity memory-safe-assembly
5492
        assembly {
5493
            mstore(0x00, m0)
5494
            mstore(0x20, m1)
5495
            mstore(0x40, m2)
5496
            mstore(0x60, m3)
5497
            mstore(0x80, m4)
5498
            mstore(0xa0, m5)
5499
            mstore(0xc0, m6)
5500
            mstore(0xe0, m7)
5501
            mstore(0x100, m8)
5502
        }
5503
    }
5504

                            
                        
5505
    function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
5506
        bytes32 m0;
5507
        bytes32 m1;
5508
        bytes32 m2;
5509
        bytes32 m3;
5510
        bytes32 m4;
5511
        bytes32 m5;
5512
        bytes32 m6;
5513
        bytes32 m7;
5514
        bytes32 m8;
5515
        bytes32 m9;
5516
        bytes32 m10;
5517
        /// @solidity memory-safe-assembly
5518
        assembly {
5519
            function writeString(pos, w) {
5520
                let length := 0
5521
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5522
                mstore(pos, length)
5523
                let shift := sub(256, shl(3, length))
5524
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5525
            }
5526
            m0 := mload(0x00)
5527
            m1 := mload(0x20)
5528
            m2 := mload(0x40)
5529
            m3 := mload(0x60)
5530
            m4 := mload(0x80)
5531
            m5 := mload(0xa0)
5532
            m6 := mload(0xc0)
5533
            m7 := mload(0xe0)
5534
            m8 := mload(0x100)
5535
            m9 := mload(0x120)
5536
            m10 := mload(0x140)
5537
            // Selector of `log(address,string,string,string)`.
5538
            mstore(0x00, 0x5d02c50b)
5539
            mstore(0x20, p0)
5540
            mstore(0x40, 0x80)
5541
            mstore(0x60, 0xc0)
5542
            mstore(0x80, 0x100)
5543
            writeString(0xa0, p1)
5544
            writeString(0xe0, p2)
5545
            writeString(0x120, p3)
5546
        }
5547
        _sendLogPayload(0x1c, 0x144);
5548
        /// @solidity memory-safe-assembly
5549
        assembly {
5550
            mstore(0x00, m0)
5551
            mstore(0x20, m1)
5552
            mstore(0x40, m2)
5553
            mstore(0x60, m3)
5554
            mstore(0x80, m4)
5555
            mstore(0xa0, m5)
5556
            mstore(0xc0, m6)
5557
            mstore(0xe0, m7)
5558
            mstore(0x100, m8)
5559
            mstore(0x120, m9)
5560
            mstore(0x140, m10)
5561
        }
5562
    }
5563

                            
                        
5564
    function log(bool p0, address p1, address p2, address p3) internal pure {
5565
        bytes32 m0;
5566
        bytes32 m1;
5567
        bytes32 m2;
5568
        bytes32 m3;
5569
        bytes32 m4;
5570
        /// @solidity memory-safe-assembly
5571
        assembly {
5572
            m0 := mload(0x00)
5573
            m1 := mload(0x20)
5574
            m2 := mload(0x40)
5575
            m3 := mload(0x60)
5576
            m4 := mload(0x80)
5577
            // Selector of `log(bool,address,address,address)`.
5578
            mstore(0x00, 0x1d14d001)
5579
            mstore(0x20, p0)
5580
            mstore(0x40, p1)
5581
            mstore(0x60, p2)
5582
            mstore(0x80, p3)
5583
        }
5584
        _sendLogPayload(0x1c, 0x84);
5585
        /// @solidity memory-safe-assembly
5586
        assembly {
5587
            mstore(0x00, m0)
5588
            mstore(0x20, m1)
5589
            mstore(0x40, m2)
5590
            mstore(0x60, m3)
5591
            mstore(0x80, m4)
5592
        }
5593
    }
5594

                            
                        
5595
    function log(bool p0, address p1, address p2, bool p3) internal pure {
5596
        bytes32 m0;
5597
        bytes32 m1;
5598
        bytes32 m2;
5599
        bytes32 m3;
5600
        bytes32 m4;
5601
        /// @solidity memory-safe-assembly
5602
        assembly {
5603
            m0 := mload(0x00)
5604
            m1 := mload(0x20)
5605
            m2 := mload(0x40)
5606
            m3 := mload(0x60)
5607
            m4 := mload(0x80)
5608
            // Selector of `log(bool,address,address,bool)`.
5609
            mstore(0x00, 0x46600be0)
5610
            mstore(0x20, p0)
5611
            mstore(0x40, p1)
5612
            mstore(0x60, p2)
5613
            mstore(0x80, p3)
5614
        }
5615
        _sendLogPayload(0x1c, 0x84);
5616
        /// @solidity memory-safe-assembly
5617
        assembly {
5618
            mstore(0x00, m0)
5619
            mstore(0x20, m1)
5620
            mstore(0x40, m2)
5621
            mstore(0x60, m3)
5622
            mstore(0x80, m4)
5623
        }
5624
    }
5625

                            
                        
5626
    function log(bool p0, address p1, address p2, uint256 p3) internal pure {
5627
        bytes32 m0;
5628
        bytes32 m1;
5629
        bytes32 m2;
5630
        bytes32 m3;
5631
        bytes32 m4;
5632
        /// @solidity memory-safe-assembly
5633
        assembly {
5634
            m0 := mload(0x00)
5635
            m1 := mload(0x20)
5636
            m2 := mload(0x40)
5637
            m3 := mload(0x60)
5638
            m4 := mload(0x80)
5639
            // Selector of `log(bool,address,address,uint256)`.
5640
            mstore(0x00, 0x0c66d1be)
5641
            mstore(0x20, p0)
5642
            mstore(0x40, p1)
5643
            mstore(0x60, p2)
5644
            mstore(0x80, p3)
5645
        }
5646
        _sendLogPayload(0x1c, 0x84);
5647
        /// @solidity memory-safe-assembly
5648
        assembly {
5649
            mstore(0x00, m0)
5650
            mstore(0x20, m1)
5651
            mstore(0x40, m2)
5652
            mstore(0x60, m3)
5653
            mstore(0x80, m4)
5654
        }
5655
    }
5656

                            
                        
5657
    function log(bool p0, address p1, address p2, bytes32 p3) internal pure {
5658
        bytes32 m0;
5659
        bytes32 m1;
5660
        bytes32 m2;
5661
        bytes32 m3;
5662
        bytes32 m4;
5663
        bytes32 m5;
5664
        bytes32 m6;
5665
        /// @solidity memory-safe-assembly
5666
        assembly {
5667
            function writeString(pos, w) {
5668
                let length := 0
5669
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5670
                mstore(pos, length)
5671
                let shift := sub(256, shl(3, length))
5672
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5673
            }
5674
            m0 := mload(0x00)
5675
            m1 := mload(0x20)
5676
            m2 := mload(0x40)
5677
            m3 := mload(0x60)
5678
            m4 := mload(0x80)
5679
            m5 := mload(0xa0)
5680
            m6 := mload(0xc0)
5681
            // Selector of `log(bool,address,address,string)`.
5682
            mstore(0x00, 0xd812a167)
5683
            mstore(0x20, p0)
5684
            mstore(0x40, p1)
5685
            mstore(0x60, p2)
5686
            mstore(0x80, 0x80)
5687
            writeString(0xa0, p3)
5688
        }
5689
        _sendLogPayload(0x1c, 0xc4);
5690
        /// @solidity memory-safe-assembly
5691
        assembly {
5692
            mstore(0x00, m0)
5693
            mstore(0x20, m1)
5694
            mstore(0x40, m2)
5695
            mstore(0x60, m3)
5696
            mstore(0x80, m4)
5697
            mstore(0xa0, m5)
5698
            mstore(0xc0, m6)
5699
        }
5700
    }
5701

                            
                        
5702
    function log(bool p0, address p1, bool p2, address p3) internal pure {
5703
        bytes32 m0;
5704
        bytes32 m1;
5705
        bytes32 m2;
5706
        bytes32 m3;
5707
        bytes32 m4;
5708
        /// @solidity memory-safe-assembly
5709
        assembly {
5710
            m0 := mload(0x00)
5711
            m1 := mload(0x20)
5712
            m2 := mload(0x40)
5713
            m3 := mload(0x60)
5714
            m4 := mload(0x80)
5715
            // Selector of `log(bool,address,bool,address)`.
5716
            mstore(0x00, 0x1c41a336)
5717
            mstore(0x20, p0)
5718
            mstore(0x40, p1)
5719
            mstore(0x60, p2)
5720
            mstore(0x80, p3)
5721
        }
5722
        _sendLogPayload(0x1c, 0x84);
5723
        /// @solidity memory-safe-assembly
5724
        assembly {
5725
            mstore(0x00, m0)
5726
            mstore(0x20, m1)
5727
            mstore(0x40, m2)
5728
            mstore(0x60, m3)
5729
            mstore(0x80, m4)
5730
        }
5731
    }
5732

                            
                        
5733
    function log(bool p0, address p1, bool p2, bool p3) internal pure {
5734
        bytes32 m0;
5735
        bytes32 m1;
5736
        bytes32 m2;
5737
        bytes32 m3;
5738
        bytes32 m4;
5739
        /// @solidity memory-safe-assembly
5740
        assembly {
5741
            m0 := mload(0x00)
5742
            m1 := mload(0x20)
5743
            m2 := mload(0x40)
5744
            m3 := mload(0x60)
5745
            m4 := mload(0x80)
5746
            // Selector of `log(bool,address,bool,bool)`.
5747
            mstore(0x00, 0x6a9c478b)
5748
            mstore(0x20, p0)
5749
            mstore(0x40, p1)
5750
            mstore(0x60, p2)
5751
            mstore(0x80, p3)
5752
        }
5753
        _sendLogPayload(0x1c, 0x84);
5754
        /// @solidity memory-safe-assembly
5755
        assembly {
5756
            mstore(0x00, m0)
5757
            mstore(0x20, m1)
5758
            mstore(0x40, m2)
5759
            mstore(0x60, m3)
5760
            mstore(0x80, m4)
5761
        }
5762
    }
5763

                            
                        
5764
    function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
5765
        bytes32 m0;
5766
        bytes32 m1;
5767
        bytes32 m2;
5768
        bytes32 m3;
5769
        bytes32 m4;
5770
        /// @solidity memory-safe-assembly
5771
        assembly {
5772
            m0 := mload(0x00)
5773
            m1 := mload(0x20)
5774
            m2 := mload(0x40)
5775
            m3 := mload(0x60)
5776
            m4 := mload(0x80)
5777
            // Selector of `log(bool,address,bool,uint256)`.
5778
            mstore(0x00, 0x07831502)
5779
            mstore(0x20, p0)
5780
            mstore(0x40, p1)
5781
            mstore(0x60, p2)
5782
            mstore(0x80, p3)
5783
        }
5784
        _sendLogPayload(0x1c, 0x84);
5785
        /// @solidity memory-safe-assembly
5786
        assembly {
5787
            mstore(0x00, m0)
5788
            mstore(0x20, m1)
5789
            mstore(0x40, m2)
5790
            mstore(0x60, m3)
5791
            mstore(0x80, m4)
5792
        }
5793
    }
5794

                            
                        
5795
    function log(bool p0, address p1, bool p2, bytes32 p3) internal pure {
5796
        bytes32 m0;
5797
        bytes32 m1;
5798
        bytes32 m2;
5799
        bytes32 m3;
5800
        bytes32 m4;
5801
        bytes32 m5;
5802
        bytes32 m6;
5803
        /// @solidity memory-safe-assembly
5804
        assembly {
5805
            function writeString(pos, w) {
5806
                let length := 0
5807
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5808
                mstore(pos, length)
5809
                let shift := sub(256, shl(3, length))
5810
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5811
            }
5812
            m0 := mload(0x00)
5813
            m1 := mload(0x20)
5814
            m2 := mload(0x40)
5815
            m3 := mload(0x60)
5816
            m4 := mload(0x80)
5817
            m5 := mload(0xa0)
5818
            m6 := mload(0xc0)
5819
            // Selector of `log(bool,address,bool,string)`.
5820
            mstore(0x00, 0x4a66cb34)
5821
            mstore(0x20, p0)
5822
            mstore(0x40, p1)
5823
            mstore(0x60, p2)
5824
            mstore(0x80, 0x80)
5825
            writeString(0xa0, p3)
5826
        }
5827
        _sendLogPayload(0x1c, 0xc4);
5828
        /// @solidity memory-safe-assembly
5829
        assembly {
5830
            mstore(0x00, m0)
5831
            mstore(0x20, m1)
5832
            mstore(0x40, m2)
5833
            mstore(0x60, m3)
5834
            mstore(0x80, m4)
5835
            mstore(0xa0, m5)
5836
            mstore(0xc0, m6)
5837
        }
5838
    }
5839

                            
                        
5840
    function log(bool p0, address p1, uint256 p2, address p3) internal pure {
5841
        bytes32 m0;
5842
        bytes32 m1;
5843
        bytes32 m2;
5844
        bytes32 m3;
5845
        bytes32 m4;
5846
        /// @solidity memory-safe-assembly
5847
        assembly {
5848
            m0 := mload(0x00)
5849
            m1 := mload(0x20)
5850
            m2 := mload(0x40)
5851
            m3 := mload(0x60)
5852
            m4 := mload(0x80)
5853
            // Selector of `log(bool,address,uint256,address)`.
5854
            mstore(0x00, 0x136b05dd)
5855
            mstore(0x20, p0)
5856
            mstore(0x40, p1)
5857
            mstore(0x60, p2)
5858
            mstore(0x80, p3)
5859
        }
5860
        _sendLogPayload(0x1c, 0x84);
5861
        /// @solidity memory-safe-assembly
5862
        assembly {
5863
            mstore(0x00, m0)
5864
            mstore(0x20, m1)
5865
            mstore(0x40, m2)
5866
            mstore(0x60, m3)
5867
            mstore(0x80, m4)
5868
        }
5869
    }
5870

                            
                        
5871
    function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
5872
        bytes32 m0;
5873
        bytes32 m1;
5874
        bytes32 m2;
5875
        bytes32 m3;
5876
        bytes32 m4;
5877
        /// @solidity memory-safe-assembly
5878
        assembly {
5879
            m0 := mload(0x00)
5880
            m1 := mload(0x20)
5881
            m2 := mload(0x40)
5882
            m3 := mload(0x60)
5883
            m4 := mload(0x80)
5884
            // Selector of `log(bool,address,uint256,bool)`.
5885
            mstore(0x00, 0xd6019f1c)
5886
            mstore(0x20, p0)
5887
            mstore(0x40, p1)
5888
            mstore(0x60, p2)
5889
            mstore(0x80, p3)
5890
        }
5891
        _sendLogPayload(0x1c, 0x84);
5892
        /// @solidity memory-safe-assembly
5893
        assembly {
5894
            mstore(0x00, m0)
5895
            mstore(0x20, m1)
5896
            mstore(0x40, m2)
5897
            mstore(0x60, m3)
5898
            mstore(0x80, m4)
5899
        }
5900
    }
5901

                            
                        
5902
    function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
5903
        bytes32 m0;
5904
        bytes32 m1;
5905
        bytes32 m2;
5906
        bytes32 m3;
5907
        bytes32 m4;
5908
        /// @solidity memory-safe-assembly
5909
        assembly {
5910
            m0 := mload(0x00)
5911
            m1 := mload(0x20)
5912
            m2 := mload(0x40)
5913
            m3 := mload(0x60)
5914
            m4 := mload(0x80)
5915
            // Selector of `log(bool,address,uint256,uint256)`.
5916
            mstore(0x00, 0x7bf181a1)
5917
            mstore(0x20, p0)
5918
            mstore(0x40, p1)
5919
            mstore(0x60, p2)
5920
            mstore(0x80, p3)
5921
        }
5922
        _sendLogPayload(0x1c, 0x84);
5923
        /// @solidity memory-safe-assembly
5924
        assembly {
5925
            mstore(0x00, m0)
5926
            mstore(0x20, m1)
5927
            mstore(0x40, m2)
5928
            mstore(0x60, m3)
5929
            mstore(0x80, m4)
5930
        }
5931
    }
5932

                            
                        
5933
    function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure {
5934
        bytes32 m0;
5935
        bytes32 m1;
5936
        bytes32 m2;
5937
        bytes32 m3;
5938
        bytes32 m4;
5939
        bytes32 m5;
5940
        bytes32 m6;
5941
        /// @solidity memory-safe-assembly
5942
        assembly {
5943
            function writeString(pos, w) {
5944
                let length := 0
5945
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5946
                mstore(pos, length)
5947
                let shift := sub(256, shl(3, length))
5948
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5949
            }
5950
            m0 := mload(0x00)
5951
            m1 := mload(0x20)
5952
            m2 := mload(0x40)
5953
            m3 := mload(0x60)
5954
            m4 := mload(0x80)
5955
            m5 := mload(0xa0)
5956
            m6 := mload(0xc0)
5957
            // Selector of `log(bool,address,uint256,string)`.
5958
            mstore(0x00, 0x51f09ff8)
5959
            mstore(0x20, p0)
5960
            mstore(0x40, p1)
5961
            mstore(0x60, p2)
5962
            mstore(0x80, 0x80)
5963
            writeString(0xa0, p3)
5964
        }
5965
        _sendLogPayload(0x1c, 0xc4);
5966
        /// @solidity memory-safe-assembly
5967
        assembly {
5968
            mstore(0x00, m0)
5969
            mstore(0x20, m1)
5970
            mstore(0x40, m2)
5971
            mstore(0x60, m3)
5972
            mstore(0x80, m4)
5973
            mstore(0xa0, m5)
5974
            mstore(0xc0, m6)
5975
        }
5976
    }
5977

                            
                        
5978
    function log(bool p0, address p1, bytes32 p2, address p3) internal pure {
5979
        bytes32 m0;
5980
        bytes32 m1;
5981
        bytes32 m2;
5982
        bytes32 m3;
5983
        bytes32 m4;
5984
        bytes32 m5;
5985
        bytes32 m6;
5986
        /// @solidity memory-safe-assembly
5987
        assembly {
5988
            function writeString(pos, w) {
5989
                let length := 0
5990
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
5991
                mstore(pos, length)
5992
                let shift := sub(256, shl(3, length))
5993
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
5994
            }
5995
            m0 := mload(0x00)
5996
            m1 := mload(0x20)
5997
            m2 := mload(0x40)
5998
            m3 := mload(0x60)
5999
            m4 := mload(0x80)
6000
            m5 := mload(0xa0)
6001
            m6 := mload(0xc0)
6002
            // Selector of `log(bool,address,string,address)`.
6003
            mstore(0x00, 0x6f7c603e)
6004
            mstore(0x20, p0)
6005
            mstore(0x40, p1)
6006
            mstore(0x60, 0x80)
6007
            mstore(0x80, p3)
6008
            writeString(0xa0, p2)
6009
        }
6010
        _sendLogPayload(0x1c, 0xc4);
6011
        /// @solidity memory-safe-assembly
6012
        assembly {
6013
            mstore(0x00, m0)
6014
            mstore(0x20, m1)
6015
            mstore(0x40, m2)
6016
            mstore(0x60, m3)
6017
            mstore(0x80, m4)
6018
            mstore(0xa0, m5)
6019
            mstore(0xc0, m6)
6020
        }
6021
    }
6022

                            
                        
6023
    function log(bool p0, address p1, bytes32 p2, bool p3) internal pure {
6024
        bytes32 m0;
6025
        bytes32 m1;
6026
        bytes32 m2;
6027
        bytes32 m3;
6028
        bytes32 m4;
6029
        bytes32 m5;
6030
        bytes32 m6;
6031
        /// @solidity memory-safe-assembly
6032
        assembly {
6033
            function writeString(pos, w) {
6034
                let length := 0
6035
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6036
                mstore(pos, length)
6037
                let shift := sub(256, shl(3, length))
6038
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6039
            }
6040
            m0 := mload(0x00)
6041
            m1 := mload(0x20)
6042
            m2 := mload(0x40)
6043
            m3 := mload(0x60)
6044
            m4 := mload(0x80)
6045
            m5 := mload(0xa0)
6046
            m6 := mload(0xc0)
6047
            // Selector of `log(bool,address,string,bool)`.
6048
            mstore(0x00, 0xe2bfd60b)
6049
            mstore(0x20, p0)
6050
            mstore(0x40, p1)
6051
            mstore(0x60, 0x80)
6052
            mstore(0x80, p3)
6053
            writeString(0xa0, p2)
6054
        }
6055
        _sendLogPayload(0x1c, 0xc4);
6056
        /// @solidity memory-safe-assembly
6057
        assembly {
6058
            mstore(0x00, m0)
6059
            mstore(0x20, m1)
6060
            mstore(0x40, m2)
6061
            mstore(0x60, m3)
6062
            mstore(0x80, m4)
6063
            mstore(0xa0, m5)
6064
            mstore(0xc0, m6)
6065
        }
6066
    }
6067

                            
                        
6068
    function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure {
6069
        bytes32 m0;
6070
        bytes32 m1;
6071
        bytes32 m2;
6072
        bytes32 m3;
6073
        bytes32 m4;
6074
        bytes32 m5;
6075
        bytes32 m6;
6076
        /// @solidity memory-safe-assembly
6077
        assembly {
6078
            function writeString(pos, w) {
6079
                let length := 0
6080
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6081
                mstore(pos, length)
6082
                let shift := sub(256, shl(3, length))
6083
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6084
            }
6085
            m0 := mload(0x00)
6086
            m1 := mload(0x20)
6087
            m2 := mload(0x40)
6088
            m3 := mload(0x60)
6089
            m4 := mload(0x80)
6090
            m5 := mload(0xa0)
6091
            m6 := mload(0xc0)
6092
            // Selector of `log(bool,address,string,uint256)`.
6093
            mstore(0x00, 0xc21f64c7)
6094
            mstore(0x20, p0)
6095
            mstore(0x40, p1)
6096
            mstore(0x60, 0x80)
6097
            mstore(0x80, p3)
6098
            writeString(0xa0, p2)
6099
        }
6100
        _sendLogPayload(0x1c, 0xc4);
6101
        /// @solidity memory-safe-assembly
6102
        assembly {
6103
            mstore(0x00, m0)
6104
            mstore(0x20, m1)
6105
            mstore(0x40, m2)
6106
            mstore(0x60, m3)
6107
            mstore(0x80, m4)
6108
            mstore(0xa0, m5)
6109
            mstore(0xc0, m6)
6110
        }
6111
    }
6112

                            
                        
6113
    function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure {
6114
        bytes32 m0;
6115
        bytes32 m1;
6116
        bytes32 m2;
6117
        bytes32 m3;
6118
        bytes32 m4;
6119
        bytes32 m5;
6120
        bytes32 m6;
6121
        bytes32 m7;
6122
        bytes32 m8;
6123
        /// @solidity memory-safe-assembly
6124
        assembly {
6125
            function writeString(pos, w) {
6126
                let length := 0
6127
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6128
                mstore(pos, length)
6129
                let shift := sub(256, shl(3, length))
6130
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6131
            }
6132
            m0 := mload(0x00)
6133
            m1 := mload(0x20)
6134
            m2 := mload(0x40)
6135
            m3 := mload(0x60)
6136
            m4 := mload(0x80)
6137
            m5 := mload(0xa0)
6138
            m6 := mload(0xc0)
6139
            m7 := mload(0xe0)
6140
            m8 := mload(0x100)
6141
            // Selector of `log(bool,address,string,string)`.
6142
            mstore(0x00, 0xa73c1db6)
6143
            mstore(0x20, p0)
6144
            mstore(0x40, p1)
6145
            mstore(0x60, 0x80)
6146
            mstore(0x80, 0xc0)
6147
            writeString(0xa0, p2)
6148
            writeString(0xe0, p3)
6149
        }
6150
        _sendLogPayload(0x1c, 0x104);
6151
        /// @solidity memory-safe-assembly
6152
        assembly {
6153
            mstore(0x00, m0)
6154
            mstore(0x20, m1)
6155
            mstore(0x40, m2)
6156
            mstore(0x60, m3)
6157
            mstore(0x80, m4)
6158
            mstore(0xa0, m5)
6159
            mstore(0xc0, m6)
6160
            mstore(0xe0, m7)
6161
            mstore(0x100, m8)
6162
        }
6163
    }
6164

                            
                        
6165
    function log(bool p0, bool p1, address p2, address p3) internal pure {
6166
        bytes32 m0;
6167
        bytes32 m1;
6168
        bytes32 m2;
6169
        bytes32 m3;
6170
        bytes32 m4;
6171
        /// @solidity memory-safe-assembly
6172
        assembly {
6173
            m0 := mload(0x00)
6174
            m1 := mload(0x20)
6175
            m2 := mload(0x40)
6176
            m3 := mload(0x60)
6177
            m4 := mload(0x80)
6178
            // Selector of `log(bool,bool,address,address)`.
6179
            mstore(0x00, 0xf4880ea4)
6180
            mstore(0x20, p0)
6181
            mstore(0x40, p1)
6182
            mstore(0x60, p2)
6183
            mstore(0x80, p3)
6184
        }
6185
        _sendLogPayload(0x1c, 0x84);
6186
        /// @solidity memory-safe-assembly
6187
        assembly {
6188
            mstore(0x00, m0)
6189
            mstore(0x20, m1)
6190
            mstore(0x40, m2)
6191
            mstore(0x60, m3)
6192
            mstore(0x80, m4)
6193
        }
6194
    }
6195

                            
                        
6196
    function log(bool p0, bool p1, address p2, bool p3) internal pure {
6197
        bytes32 m0;
6198
        bytes32 m1;
6199
        bytes32 m2;
6200
        bytes32 m3;
6201
        bytes32 m4;
6202
        /// @solidity memory-safe-assembly
6203
        assembly {
6204
            m0 := mload(0x00)
6205
            m1 := mload(0x20)
6206
            m2 := mload(0x40)
6207
            m3 := mload(0x60)
6208
            m4 := mload(0x80)
6209
            // Selector of `log(bool,bool,address,bool)`.
6210
            mstore(0x00, 0xc0a302d8)
6211
            mstore(0x20, p0)
6212
            mstore(0x40, p1)
6213
            mstore(0x60, p2)
6214
            mstore(0x80, p3)
6215
        }
6216
        _sendLogPayload(0x1c, 0x84);
6217
        /// @solidity memory-safe-assembly
6218
        assembly {
6219
            mstore(0x00, m0)
6220
            mstore(0x20, m1)
6221
            mstore(0x40, m2)
6222
            mstore(0x60, m3)
6223
            mstore(0x80, m4)
6224
        }
6225
    }
6226

                            
                        
6227
    function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
6228
        bytes32 m0;
6229
        bytes32 m1;
6230
        bytes32 m2;
6231
        bytes32 m3;
6232
        bytes32 m4;
6233
        /// @solidity memory-safe-assembly
6234
        assembly {
6235
            m0 := mload(0x00)
6236
            m1 := mload(0x20)
6237
            m2 := mload(0x40)
6238
            m3 := mload(0x60)
6239
            m4 := mload(0x80)
6240
            // Selector of `log(bool,bool,address,uint256)`.
6241
            mstore(0x00, 0x4c123d57)
6242
            mstore(0x20, p0)
6243
            mstore(0x40, p1)
6244
            mstore(0x60, p2)
6245
            mstore(0x80, p3)
6246
        }
6247
        _sendLogPayload(0x1c, 0x84);
6248
        /// @solidity memory-safe-assembly
6249
        assembly {
6250
            mstore(0x00, m0)
6251
            mstore(0x20, m1)
6252
            mstore(0x40, m2)
6253
            mstore(0x60, m3)
6254
            mstore(0x80, m4)
6255
        }
6256
    }
6257

                            
                        
6258
    function log(bool p0, bool p1, address p2, bytes32 p3) internal pure {
6259
        bytes32 m0;
6260
        bytes32 m1;
6261
        bytes32 m2;
6262
        bytes32 m3;
6263
        bytes32 m4;
6264
        bytes32 m5;
6265
        bytes32 m6;
6266
        /// @solidity memory-safe-assembly
6267
        assembly {
6268
            function writeString(pos, w) {
6269
                let length := 0
6270
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6271
                mstore(pos, length)
6272
                let shift := sub(256, shl(3, length))
6273
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6274
            }
6275
            m0 := mload(0x00)
6276
            m1 := mload(0x20)
6277
            m2 := mload(0x40)
6278
            m3 := mload(0x60)
6279
            m4 := mload(0x80)
6280
            m5 := mload(0xa0)
6281
            m6 := mload(0xc0)
6282
            // Selector of `log(bool,bool,address,string)`.
6283
            mstore(0x00, 0xa0a47963)
6284
            mstore(0x20, p0)
6285
            mstore(0x40, p1)
6286
            mstore(0x60, p2)
6287
            mstore(0x80, 0x80)
6288
            writeString(0xa0, p3)
6289
        }
6290
        _sendLogPayload(0x1c, 0xc4);
6291
        /// @solidity memory-safe-assembly
6292
        assembly {
6293
            mstore(0x00, m0)
6294
            mstore(0x20, m1)
6295
            mstore(0x40, m2)
6296
            mstore(0x60, m3)
6297
            mstore(0x80, m4)
6298
            mstore(0xa0, m5)
6299
            mstore(0xc0, m6)
6300
        }
6301
    }
6302

                            
                        
6303
    function log(bool p0, bool p1, bool p2, address p3) internal pure {
6304
        bytes32 m0;
6305
        bytes32 m1;
6306
        bytes32 m2;
6307
        bytes32 m3;
6308
        bytes32 m4;
6309
        /// @solidity memory-safe-assembly
6310
        assembly {
6311
            m0 := mload(0x00)
6312
            m1 := mload(0x20)
6313
            m2 := mload(0x40)
6314
            m3 := mload(0x60)
6315
            m4 := mload(0x80)
6316
            // Selector of `log(bool,bool,bool,address)`.
6317
            mstore(0x00, 0x8c329b1a)
6318
            mstore(0x20, p0)
6319
            mstore(0x40, p1)
6320
            mstore(0x60, p2)
6321
            mstore(0x80, p3)
6322
        }
6323
        _sendLogPayload(0x1c, 0x84);
6324
        /// @solidity memory-safe-assembly
6325
        assembly {
6326
            mstore(0x00, m0)
6327
            mstore(0x20, m1)
6328
            mstore(0x40, m2)
6329
            mstore(0x60, m3)
6330
            mstore(0x80, m4)
6331
        }
6332
    }
6333

                            
                        
6334
    function log(bool p0, bool p1, bool p2, bool p3) internal pure {
6335
        bytes32 m0;
6336
        bytes32 m1;
6337
        bytes32 m2;
6338
        bytes32 m3;
6339
        bytes32 m4;
6340
        /// @solidity memory-safe-assembly
6341
        assembly {
6342
            m0 := mload(0x00)
6343
            m1 := mload(0x20)
6344
            m2 := mload(0x40)
6345
            m3 := mload(0x60)
6346
            m4 := mload(0x80)
6347
            // Selector of `log(bool,bool,bool,bool)`.
6348
            mstore(0x00, 0x3b2a5ce0)
6349
            mstore(0x20, p0)
6350
            mstore(0x40, p1)
6351
            mstore(0x60, p2)
6352
            mstore(0x80, p3)
6353
        }
6354
        _sendLogPayload(0x1c, 0x84);
6355
        /// @solidity memory-safe-assembly
6356
        assembly {
6357
            mstore(0x00, m0)
6358
            mstore(0x20, m1)
6359
            mstore(0x40, m2)
6360
            mstore(0x60, m3)
6361
            mstore(0x80, m4)
6362
        }
6363
    }
6364

                            
                        
6365
    function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
6366
        bytes32 m0;
6367
        bytes32 m1;
6368
        bytes32 m2;
6369
        bytes32 m3;
6370
        bytes32 m4;
6371
        /// @solidity memory-safe-assembly
6372
        assembly {
6373
            m0 := mload(0x00)
6374
            m1 := mload(0x20)
6375
            m2 := mload(0x40)
6376
            m3 := mload(0x60)
6377
            m4 := mload(0x80)
6378
            // Selector of `log(bool,bool,bool,uint256)`.
6379
            mstore(0x00, 0x6d7045c1)
6380
            mstore(0x20, p0)
6381
            mstore(0x40, p1)
6382
            mstore(0x60, p2)
6383
            mstore(0x80, p3)
6384
        }
6385
        _sendLogPayload(0x1c, 0x84);
6386
        /// @solidity memory-safe-assembly
6387
        assembly {
6388
            mstore(0x00, m0)
6389
            mstore(0x20, m1)
6390
            mstore(0x40, m2)
6391
            mstore(0x60, m3)
6392
            mstore(0x80, m4)
6393
        }
6394
    }
6395

                            
                        
6396
    function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure {
6397
        bytes32 m0;
6398
        bytes32 m1;
6399
        bytes32 m2;
6400
        bytes32 m3;
6401
        bytes32 m4;
6402
        bytes32 m5;
6403
        bytes32 m6;
6404
        /// @solidity memory-safe-assembly
6405
        assembly {
6406
            function writeString(pos, w) {
6407
                let length := 0
6408
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6409
                mstore(pos, length)
6410
                let shift := sub(256, shl(3, length))
6411
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6412
            }
6413
            m0 := mload(0x00)
6414
            m1 := mload(0x20)
6415
            m2 := mload(0x40)
6416
            m3 := mload(0x60)
6417
            m4 := mload(0x80)
6418
            m5 := mload(0xa0)
6419
            m6 := mload(0xc0)
6420
            // Selector of `log(bool,bool,bool,string)`.
6421
            mstore(0x00, 0x2ae408d4)
6422
            mstore(0x20, p0)
6423
            mstore(0x40, p1)
6424
            mstore(0x60, p2)
6425
            mstore(0x80, 0x80)
6426
            writeString(0xa0, p3)
6427
        }
6428
        _sendLogPayload(0x1c, 0xc4);
6429
        /// @solidity memory-safe-assembly
6430
        assembly {
6431
            mstore(0x00, m0)
6432
            mstore(0x20, m1)
6433
            mstore(0x40, m2)
6434
            mstore(0x60, m3)
6435
            mstore(0x80, m4)
6436
            mstore(0xa0, m5)
6437
            mstore(0xc0, m6)
6438
        }
6439
    }
6440

                            
                        
6441
    function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
6442
        bytes32 m0;
6443
        bytes32 m1;
6444
        bytes32 m2;
6445
        bytes32 m3;
6446
        bytes32 m4;
6447
        /// @solidity memory-safe-assembly
6448
        assembly {
6449
            m0 := mload(0x00)
6450
            m1 := mload(0x20)
6451
            m2 := mload(0x40)
6452
            m3 := mload(0x60)
6453
            m4 := mload(0x80)
6454
            // Selector of `log(bool,bool,uint256,address)`.
6455
            mstore(0x00, 0x54a7a9a0)
6456
            mstore(0x20, p0)
6457
            mstore(0x40, p1)
6458
            mstore(0x60, p2)
6459
            mstore(0x80, p3)
6460
        }
6461
        _sendLogPayload(0x1c, 0x84);
6462
        /// @solidity memory-safe-assembly
6463
        assembly {
6464
            mstore(0x00, m0)
6465
            mstore(0x20, m1)
6466
            mstore(0x40, m2)
6467
            mstore(0x60, m3)
6468
            mstore(0x80, m4)
6469
        }
6470
    }
6471

                            
                        
6472
    function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
6473
        bytes32 m0;
6474
        bytes32 m1;
6475
        bytes32 m2;
6476
        bytes32 m3;
6477
        bytes32 m4;
6478
        /// @solidity memory-safe-assembly
6479
        assembly {
6480
            m0 := mload(0x00)
6481
            m1 := mload(0x20)
6482
            m2 := mload(0x40)
6483
            m3 := mload(0x60)
6484
            m4 := mload(0x80)
6485
            // Selector of `log(bool,bool,uint256,bool)`.
6486
            mstore(0x00, 0x619e4d0e)
6487
            mstore(0x20, p0)
6488
            mstore(0x40, p1)
6489
            mstore(0x60, p2)
6490
            mstore(0x80, p3)
6491
        }
6492
        _sendLogPayload(0x1c, 0x84);
6493
        /// @solidity memory-safe-assembly
6494
        assembly {
6495
            mstore(0x00, m0)
6496
            mstore(0x20, m1)
6497
            mstore(0x40, m2)
6498
            mstore(0x60, m3)
6499
            mstore(0x80, m4)
6500
        }
6501
    }
6502

                            
                        
6503
    function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
6504
        bytes32 m0;
6505
        bytes32 m1;
6506
        bytes32 m2;
6507
        bytes32 m3;
6508
        bytes32 m4;
6509
        /// @solidity memory-safe-assembly
6510
        assembly {
6511
            m0 := mload(0x00)
6512
            m1 := mload(0x20)
6513
            m2 := mload(0x40)
6514
            m3 := mload(0x60)
6515
            m4 := mload(0x80)
6516
            // Selector of `log(bool,bool,uint256,uint256)`.
6517
            mstore(0x00, 0x0bb00eab)
6518
            mstore(0x20, p0)
6519
            mstore(0x40, p1)
6520
            mstore(0x60, p2)
6521
            mstore(0x80, p3)
6522
        }
6523
        _sendLogPayload(0x1c, 0x84);
6524
        /// @solidity memory-safe-assembly
6525
        assembly {
6526
            mstore(0x00, m0)
6527
            mstore(0x20, m1)
6528
            mstore(0x40, m2)
6529
            mstore(0x60, m3)
6530
            mstore(0x80, m4)
6531
        }
6532
    }
6533

                            
                        
6534
    function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure {
6535
        bytes32 m0;
6536
        bytes32 m1;
6537
        bytes32 m2;
6538
        bytes32 m3;
6539
        bytes32 m4;
6540
        bytes32 m5;
6541
        bytes32 m6;
6542
        /// @solidity memory-safe-assembly
6543
        assembly {
6544
            function writeString(pos, w) {
6545
                let length := 0
6546
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6547
                mstore(pos, length)
6548
                let shift := sub(256, shl(3, length))
6549
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6550
            }
6551
            m0 := mload(0x00)
6552
            m1 := mload(0x20)
6553
            m2 := mload(0x40)
6554
            m3 := mload(0x60)
6555
            m4 := mload(0x80)
6556
            m5 := mload(0xa0)
6557
            m6 := mload(0xc0)
6558
            // Selector of `log(bool,bool,uint256,string)`.
6559
            mstore(0x00, 0x7dd4d0e0)
6560
            mstore(0x20, p0)
6561
            mstore(0x40, p1)
6562
            mstore(0x60, p2)
6563
            mstore(0x80, 0x80)
6564
            writeString(0xa0, p3)
6565
        }
6566
        _sendLogPayload(0x1c, 0xc4);
6567
        /// @solidity memory-safe-assembly
6568
        assembly {
6569
            mstore(0x00, m0)
6570
            mstore(0x20, m1)
6571
            mstore(0x40, m2)
6572
            mstore(0x60, m3)
6573
            mstore(0x80, m4)
6574
            mstore(0xa0, m5)
6575
            mstore(0xc0, m6)
6576
        }
6577
    }
6578

                            
                        
6579
    function log(bool p0, bool p1, bytes32 p2, address p3) internal pure {
6580
        bytes32 m0;
6581
        bytes32 m1;
6582
        bytes32 m2;
6583
        bytes32 m3;
6584
        bytes32 m4;
6585
        bytes32 m5;
6586
        bytes32 m6;
6587
        /// @solidity memory-safe-assembly
6588
        assembly {
6589
            function writeString(pos, w) {
6590
                let length := 0
6591
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6592
                mstore(pos, length)
6593
                let shift := sub(256, shl(3, length))
6594
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6595
            }
6596
            m0 := mload(0x00)
6597
            m1 := mload(0x20)
6598
            m2 := mload(0x40)
6599
            m3 := mload(0x60)
6600
            m4 := mload(0x80)
6601
            m5 := mload(0xa0)
6602
            m6 := mload(0xc0)
6603
            // Selector of `log(bool,bool,string,address)`.
6604
            mstore(0x00, 0xf9ad2b89)
6605
            mstore(0x20, p0)
6606
            mstore(0x40, p1)
6607
            mstore(0x60, 0x80)
6608
            mstore(0x80, p3)
6609
            writeString(0xa0, p2)
6610
        }
6611
        _sendLogPayload(0x1c, 0xc4);
6612
        /// @solidity memory-safe-assembly
6613
        assembly {
6614
            mstore(0x00, m0)
6615
            mstore(0x20, m1)
6616
            mstore(0x40, m2)
6617
            mstore(0x60, m3)
6618
            mstore(0x80, m4)
6619
            mstore(0xa0, m5)
6620
            mstore(0xc0, m6)
6621
        }
6622
    }
6623

                            
                        
6624
    function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure {
6625
        bytes32 m0;
6626
        bytes32 m1;
6627
        bytes32 m2;
6628
        bytes32 m3;
6629
        bytes32 m4;
6630
        bytes32 m5;
6631
        bytes32 m6;
6632
        /// @solidity memory-safe-assembly
6633
        assembly {
6634
            function writeString(pos, w) {
6635
                let length := 0
6636
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6637
                mstore(pos, length)
6638
                let shift := sub(256, shl(3, length))
6639
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6640
            }
6641
            m0 := mload(0x00)
6642
            m1 := mload(0x20)
6643
            m2 := mload(0x40)
6644
            m3 := mload(0x60)
6645
            m4 := mload(0x80)
6646
            m5 := mload(0xa0)
6647
            m6 := mload(0xc0)
6648
            // Selector of `log(bool,bool,string,bool)`.
6649
            mstore(0x00, 0xb857163a)
6650
            mstore(0x20, p0)
6651
            mstore(0x40, p1)
6652
            mstore(0x60, 0x80)
6653
            mstore(0x80, p3)
6654
            writeString(0xa0, p2)
6655
        }
6656
        _sendLogPayload(0x1c, 0xc4);
6657
        /// @solidity memory-safe-assembly
6658
        assembly {
6659
            mstore(0x00, m0)
6660
            mstore(0x20, m1)
6661
            mstore(0x40, m2)
6662
            mstore(0x60, m3)
6663
            mstore(0x80, m4)
6664
            mstore(0xa0, m5)
6665
            mstore(0xc0, m6)
6666
        }
6667
    }
6668

                            
                        
6669
    function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure {
6670
        bytes32 m0;
6671
        bytes32 m1;
6672
        bytes32 m2;
6673
        bytes32 m3;
6674
        bytes32 m4;
6675
        bytes32 m5;
6676
        bytes32 m6;
6677
        /// @solidity memory-safe-assembly
6678
        assembly {
6679
            function writeString(pos, w) {
6680
                let length := 0
6681
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6682
                mstore(pos, length)
6683
                let shift := sub(256, shl(3, length))
6684
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6685
            }
6686
            m0 := mload(0x00)
6687
            m1 := mload(0x20)
6688
            m2 := mload(0x40)
6689
            m3 := mload(0x60)
6690
            m4 := mload(0x80)
6691
            m5 := mload(0xa0)
6692
            m6 := mload(0xc0)
6693
            // Selector of `log(bool,bool,string,uint256)`.
6694
            mstore(0x00, 0xe3a9ca2f)
6695
            mstore(0x20, p0)
6696
            mstore(0x40, p1)
6697
            mstore(0x60, 0x80)
6698
            mstore(0x80, p3)
6699
            writeString(0xa0, p2)
6700
        }
6701
        _sendLogPayload(0x1c, 0xc4);
6702
        /// @solidity memory-safe-assembly
6703
        assembly {
6704
            mstore(0x00, m0)
6705
            mstore(0x20, m1)
6706
            mstore(0x40, m2)
6707
            mstore(0x60, m3)
6708
            mstore(0x80, m4)
6709
            mstore(0xa0, m5)
6710
            mstore(0xc0, m6)
6711
        }
6712
    }
6713

                            
                        
6714
    function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
6715
        bytes32 m0;
6716
        bytes32 m1;
6717
        bytes32 m2;
6718
        bytes32 m3;
6719
        bytes32 m4;
6720
        bytes32 m5;
6721
        bytes32 m6;
6722
        bytes32 m7;
6723
        bytes32 m8;
6724
        /// @solidity memory-safe-assembly
6725
        assembly {
6726
            function writeString(pos, w) {
6727
                let length := 0
6728
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6729
                mstore(pos, length)
6730
                let shift := sub(256, shl(3, length))
6731
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6732
            }
6733
            m0 := mload(0x00)
6734
            m1 := mload(0x20)
6735
            m2 := mload(0x40)
6736
            m3 := mload(0x60)
6737
            m4 := mload(0x80)
6738
            m5 := mload(0xa0)
6739
            m6 := mload(0xc0)
6740
            m7 := mload(0xe0)
6741
            m8 := mload(0x100)
6742
            // Selector of `log(bool,bool,string,string)`.
6743
            mstore(0x00, 0x6d1e8751)
6744
            mstore(0x20, p0)
6745
            mstore(0x40, p1)
6746
            mstore(0x60, 0x80)
6747
            mstore(0x80, 0xc0)
6748
            writeString(0xa0, p2)
6749
            writeString(0xe0, p3)
6750
        }
6751
        _sendLogPayload(0x1c, 0x104);
6752
        /// @solidity memory-safe-assembly
6753
        assembly {
6754
            mstore(0x00, m0)
6755
            mstore(0x20, m1)
6756
            mstore(0x40, m2)
6757
            mstore(0x60, m3)
6758
            mstore(0x80, m4)
6759
            mstore(0xa0, m5)
6760
            mstore(0xc0, m6)
6761
            mstore(0xe0, m7)
6762
            mstore(0x100, m8)
6763
        }
6764
    }
6765

                            
                        
6766
    function log(bool p0, uint256 p1, address p2, address p3) internal pure {
6767
        bytes32 m0;
6768
        bytes32 m1;
6769
        bytes32 m2;
6770
        bytes32 m3;
6771
        bytes32 m4;
6772
        /// @solidity memory-safe-assembly
6773
        assembly {
6774
            m0 := mload(0x00)
6775
            m1 := mload(0x20)
6776
            m2 := mload(0x40)
6777
            m3 := mload(0x60)
6778
            m4 := mload(0x80)
6779
            // Selector of `log(bool,uint256,address,address)`.
6780
            mstore(0x00, 0x26f560a8)
6781
            mstore(0x20, p0)
6782
            mstore(0x40, p1)
6783
            mstore(0x60, p2)
6784
            mstore(0x80, p3)
6785
        }
6786
        _sendLogPayload(0x1c, 0x84);
6787
        /// @solidity memory-safe-assembly
6788
        assembly {
6789
            mstore(0x00, m0)
6790
            mstore(0x20, m1)
6791
            mstore(0x40, m2)
6792
            mstore(0x60, m3)
6793
            mstore(0x80, m4)
6794
        }
6795
    }
6796

                            
                        
6797
    function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
6798
        bytes32 m0;
6799
        bytes32 m1;
6800
        bytes32 m2;
6801
        bytes32 m3;
6802
        bytes32 m4;
6803
        /// @solidity memory-safe-assembly
6804
        assembly {
6805
            m0 := mload(0x00)
6806
            m1 := mload(0x20)
6807
            m2 := mload(0x40)
6808
            m3 := mload(0x60)
6809
            m4 := mload(0x80)
6810
            // Selector of `log(bool,uint256,address,bool)`.
6811
            mstore(0x00, 0xb4c314ff)
6812
            mstore(0x20, p0)
6813
            mstore(0x40, p1)
6814
            mstore(0x60, p2)
6815
            mstore(0x80, p3)
6816
        }
6817
        _sendLogPayload(0x1c, 0x84);
6818
        /// @solidity memory-safe-assembly
6819
        assembly {
6820
            mstore(0x00, m0)
6821
            mstore(0x20, m1)
6822
            mstore(0x40, m2)
6823
            mstore(0x60, m3)
6824
            mstore(0x80, m4)
6825
        }
6826
    }
6827

                            
                        
6828
    function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
6829
        bytes32 m0;
6830
        bytes32 m1;
6831
        bytes32 m2;
6832
        bytes32 m3;
6833
        bytes32 m4;
6834
        /// @solidity memory-safe-assembly
6835
        assembly {
6836
            m0 := mload(0x00)
6837
            m1 := mload(0x20)
6838
            m2 := mload(0x40)
6839
            m3 := mload(0x60)
6840
            m4 := mload(0x80)
6841
            // Selector of `log(bool,uint256,address,uint256)`.
6842
            mstore(0x00, 0x1537dc87)
6843
            mstore(0x20, p0)
6844
            mstore(0x40, p1)
6845
            mstore(0x60, p2)
6846
            mstore(0x80, p3)
6847
        }
6848
        _sendLogPayload(0x1c, 0x84);
6849
        /// @solidity memory-safe-assembly
6850
        assembly {
6851
            mstore(0x00, m0)
6852
            mstore(0x20, m1)
6853
            mstore(0x40, m2)
6854
            mstore(0x60, m3)
6855
            mstore(0x80, m4)
6856
        }
6857
    }
6858

                            
                        
6859
    function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure {
6860
        bytes32 m0;
6861
        bytes32 m1;
6862
        bytes32 m2;
6863
        bytes32 m3;
6864
        bytes32 m4;
6865
        bytes32 m5;
6866
        bytes32 m6;
6867
        /// @solidity memory-safe-assembly
6868
        assembly {
6869
            function writeString(pos, w) {
6870
                let length := 0
6871
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
6872
                mstore(pos, length)
6873
                let shift := sub(256, shl(3, length))
6874
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
6875
            }
6876
            m0 := mload(0x00)
6877
            m1 := mload(0x20)
6878
            m2 := mload(0x40)
6879
            m3 := mload(0x60)
6880
            m4 := mload(0x80)
6881
            m5 := mload(0xa0)
6882
            m6 := mload(0xc0)
6883
            // Selector of `log(bool,uint256,address,string)`.
6884
            mstore(0x00, 0x1bb3b09a)
6885
            mstore(0x20, p0)
6886
            mstore(0x40, p1)
6887
            mstore(0x60, p2)
6888
            mstore(0x80, 0x80)
6889
            writeString(0xa0, p3)
6890
        }
6891
        _sendLogPayload(0x1c, 0xc4);
6892
        /// @solidity memory-safe-assembly
6893
        assembly {
6894
            mstore(0x00, m0)
6895
            mstore(0x20, m1)
6896
            mstore(0x40, m2)
6897
            mstore(0x60, m3)
6898
            mstore(0x80, m4)
6899
            mstore(0xa0, m5)
6900
            mstore(0xc0, m6)
6901
        }
6902
    }
6903

                            
                        
6904
    function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
6905
        bytes32 m0;
6906
        bytes32 m1;
6907
        bytes32 m2;
6908
        bytes32 m3;
6909
        bytes32 m4;
6910
        /// @solidity memory-safe-assembly
6911
        assembly {
6912
            m0 := mload(0x00)
6913
            m1 := mload(0x20)
6914
            m2 := mload(0x40)
6915
            m3 := mload(0x60)
6916
            m4 := mload(0x80)
6917
            // Selector of `log(bool,uint256,bool,address)`.
6918
            mstore(0x00, 0x9acd3616)
6919
            mstore(0x20, p0)
6920
            mstore(0x40, p1)
6921
            mstore(0x60, p2)
6922
            mstore(0x80, p3)
6923
        }
6924
        _sendLogPayload(0x1c, 0x84);
6925
        /// @solidity memory-safe-assembly
6926
        assembly {
6927
            mstore(0x00, m0)
6928
            mstore(0x20, m1)
6929
            mstore(0x40, m2)
6930
            mstore(0x60, m3)
6931
            mstore(0x80, m4)
6932
        }
6933
    }
6934

                            
                        
6935
    function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
6936
        bytes32 m0;
6937
        bytes32 m1;
6938
        bytes32 m2;
6939
        bytes32 m3;
6940
        bytes32 m4;
6941
        /// @solidity memory-safe-assembly
6942
        assembly {
6943
            m0 := mload(0x00)
6944
            m1 := mload(0x20)
6945
            m2 := mload(0x40)
6946
            m3 := mload(0x60)
6947
            m4 := mload(0x80)
6948
            // Selector of `log(bool,uint256,bool,bool)`.
6949
            mstore(0x00, 0xceb5f4d7)
6950
            mstore(0x20, p0)
6951
            mstore(0x40, p1)
6952
            mstore(0x60, p2)
6953
            mstore(0x80, p3)
6954
        }
6955
        _sendLogPayload(0x1c, 0x84);
6956
        /// @solidity memory-safe-assembly
6957
        assembly {
6958
            mstore(0x00, m0)
6959
            mstore(0x20, m1)
6960
            mstore(0x40, m2)
6961
            mstore(0x60, m3)
6962
            mstore(0x80, m4)
6963
        }
6964
    }
6965

                            
                        
6966
    function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
6967
        bytes32 m0;
6968
        bytes32 m1;
6969
        bytes32 m2;
6970
        bytes32 m3;
6971
        bytes32 m4;
6972
        /// @solidity memory-safe-assembly
6973
        assembly {
6974
            m0 := mload(0x00)
6975
            m1 := mload(0x20)
6976
            m2 := mload(0x40)
6977
            m3 := mload(0x60)
6978
            m4 := mload(0x80)
6979
            // Selector of `log(bool,uint256,bool,uint256)`.
6980
            mstore(0x00, 0x7f9bbca2)
6981
            mstore(0x20, p0)
6982
            mstore(0x40, p1)
6983
            mstore(0x60, p2)
6984
            mstore(0x80, p3)
6985
        }
6986
        _sendLogPayload(0x1c, 0x84);
6987
        /// @solidity memory-safe-assembly
6988
        assembly {
6989
            mstore(0x00, m0)
6990
            mstore(0x20, m1)
6991
            mstore(0x40, m2)
6992
            mstore(0x60, m3)
6993
            mstore(0x80, m4)
6994
        }
6995
    }
6996

                            
                        
6997
    function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure {
6998
        bytes32 m0;
6999
        bytes32 m1;
7000
        bytes32 m2;
7001
        bytes32 m3;
7002
        bytes32 m4;
7003
        bytes32 m5;
7004
        bytes32 m6;
7005
        /// @solidity memory-safe-assembly
7006
        assembly {
7007
            function writeString(pos, w) {
7008
                let length := 0
7009
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7010
                mstore(pos, length)
7011
                let shift := sub(256, shl(3, length))
7012
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7013
            }
7014
            m0 := mload(0x00)
7015
            m1 := mload(0x20)
7016
            m2 := mload(0x40)
7017
            m3 := mload(0x60)
7018
            m4 := mload(0x80)
7019
            m5 := mload(0xa0)
7020
            m6 := mload(0xc0)
7021
            // Selector of `log(bool,uint256,bool,string)`.
7022
            mstore(0x00, 0x9143dbb1)
7023
            mstore(0x20, p0)
7024
            mstore(0x40, p1)
7025
            mstore(0x60, p2)
7026
            mstore(0x80, 0x80)
7027
            writeString(0xa0, p3)
7028
        }
7029
        _sendLogPayload(0x1c, 0xc4);
7030
        /// @solidity memory-safe-assembly
7031
        assembly {
7032
            mstore(0x00, m0)
7033
            mstore(0x20, m1)
7034
            mstore(0x40, m2)
7035
            mstore(0x60, m3)
7036
            mstore(0x80, m4)
7037
            mstore(0xa0, m5)
7038
            mstore(0xc0, m6)
7039
        }
7040
    }
7041

                            
                        
7042
    function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
7043
        bytes32 m0;
7044
        bytes32 m1;
7045
        bytes32 m2;
7046
        bytes32 m3;
7047
        bytes32 m4;
7048
        /// @solidity memory-safe-assembly
7049
        assembly {
7050
            m0 := mload(0x00)
7051
            m1 := mload(0x20)
7052
            m2 := mload(0x40)
7053
            m3 := mload(0x60)
7054
            m4 := mload(0x80)
7055
            // Selector of `log(bool,uint256,uint256,address)`.
7056
            mstore(0x00, 0x00dd87b9)
7057
            mstore(0x20, p0)
7058
            mstore(0x40, p1)
7059
            mstore(0x60, p2)
7060
            mstore(0x80, p3)
7061
        }
7062
        _sendLogPayload(0x1c, 0x84);
7063
        /// @solidity memory-safe-assembly
7064
        assembly {
7065
            mstore(0x00, m0)
7066
            mstore(0x20, m1)
7067
            mstore(0x40, m2)
7068
            mstore(0x60, m3)
7069
            mstore(0x80, m4)
7070
        }
7071
    }
7072

                            
                        
7073
    function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
7074
        bytes32 m0;
7075
        bytes32 m1;
7076
        bytes32 m2;
7077
        bytes32 m3;
7078
        bytes32 m4;
7079
        /// @solidity memory-safe-assembly
7080
        assembly {
7081
            m0 := mload(0x00)
7082
            m1 := mload(0x20)
7083
            m2 := mload(0x40)
7084
            m3 := mload(0x60)
7085
            m4 := mload(0x80)
7086
            // Selector of `log(bool,uint256,uint256,bool)`.
7087
            mstore(0x00, 0xbe984353)
7088
            mstore(0x20, p0)
7089
            mstore(0x40, p1)
7090
            mstore(0x60, p2)
7091
            mstore(0x80, p3)
7092
        }
7093
        _sendLogPayload(0x1c, 0x84);
7094
        /// @solidity memory-safe-assembly
7095
        assembly {
7096
            mstore(0x00, m0)
7097
            mstore(0x20, m1)
7098
            mstore(0x40, m2)
7099
            mstore(0x60, m3)
7100
            mstore(0x80, m4)
7101
        }
7102
    }
7103

                            
                        
7104
    function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
7105
        bytes32 m0;
7106
        bytes32 m1;
7107
        bytes32 m2;
7108
        bytes32 m3;
7109
        bytes32 m4;
7110
        /// @solidity memory-safe-assembly
7111
        assembly {
7112
            m0 := mload(0x00)
7113
            m1 := mload(0x20)
7114
            m2 := mload(0x40)
7115
            m3 := mload(0x60)
7116
            m4 := mload(0x80)
7117
            // Selector of `log(bool,uint256,uint256,uint256)`.
7118
            mstore(0x00, 0x374bb4b2)
7119
            mstore(0x20, p0)
7120
            mstore(0x40, p1)
7121
            mstore(0x60, p2)
7122
            mstore(0x80, p3)
7123
        }
7124
        _sendLogPayload(0x1c, 0x84);
7125
        /// @solidity memory-safe-assembly
7126
        assembly {
7127
            mstore(0x00, m0)
7128
            mstore(0x20, m1)
7129
            mstore(0x40, m2)
7130
            mstore(0x60, m3)
7131
            mstore(0x80, m4)
7132
        }
7133
    }
7134

                            
                        
7135
    function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
7136
        bytes32 m0;
7137
        bytes32 m1;
7138
        bytes32 m2;
7139
        bytes32 m3;
7140
        bytes32 m4;
7141
        bytes32 m5;
7142
        bytes32 m6;
7143
        /// @solidity memory-safe-assembly
7144
        assembly {
7145
            function writeString(pos, w) {
7146
                let length := 0
7147
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7148
                mstore(pos, length)
7149
                let shift := sub(256, shl(3, length))
7150
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7151
            }
7152
            m0 := mload(0x00)
7153
            m1 := mload(0x20)
7154
            m2 := mload(0x40)
7155
            m3 := mload(0x60)
7156
            m4 := mload(0x80)
7157
            m5 := mload(0xa0)
7158
            m6 := mload(0xc0)
7159
            // Selector of `log(bool,uint256,uint256,string)`.
7160
            mstore(0x00, 0x8e69fb5d)
7161
            mstore(0x20, p0)
7162
            mstore(0x40, p1)
7163
            mstore(0x60, p2)
7164
            mstore(0x80, 0x80)
7165
            writeString(0xa0, p3)
7166
        }
7167
        _sendLogPayload(0x1c, 0xc4);
7168
        /// @solidity memory-safe-assembly
7169
        assembly {
7170
            mstore(0x00, m0)
7171
            mstore(0x20, m1)
7172
            mstore(0x40, m2)
7173
            mstore(0x60, m3)
7174
            mstore(0x80, m4)
7175
            mstore(0xa0, m5)
7176
            mstore(0xc0, m6)
7177
        }
7178
    }
7179

                            
                        
7180
    function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure {
7181
        bytes32 m0;
7182
        bytes32 m1;
7183
        bytes32 m2;
7184
        bytes32 m3;
7185
        bytes32 m4;
7186
        bytes32 m5;
7187
        bytes32 m6;
7188
        /// @solidity memory-safe-assembly
7189
        assembly {
7190
            function writeString(pos, w) {
7191
                let length := 0
7192
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7193
                mstore(pos, length)
7194
                let shift := sub(256, shl(3, length))
7195
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7196
            }
7197
            m0 := mload(0x00)
7198
            m1 := mload(0x20)
7199
            m2 := mload(0x40)
7200
            m3 := mload(0x60)
7201
            m4 := mload(0x80)
7202
            m5 := mload(0xa0)
7203
            m6 := mload(0xc0)
7204
            // Selector of `log(bool,uint256,string,address)`.
7205
            mstore(0x00, 0xfedd1fff)
7206
            mstore(0x20, p0)
7207
            mstore(0x40, p1)
7208
            mstore(0x60, 0x80)
7209
            mstore(0x80, p3)
7210
            writeString(0xa0, p2)
7211
        }
7212
        _sendLogPayload(0x1c, 0xc4);
7213
        /// @solidity memory-safe-assembly
7214
        assembly {
7215
            mstore(0x00, m0)
7216
            mstore(0x20, m1)
7217
            mstore(0x40, m2)
7218
            mstore(0x60, m3)
7219
            mstore(0x80, m4)
7220
            mstore(0xa0, m5)
7221
            mstore(0xc0, m6)
7222
        }
7223
    }
7224

                            
                        
7225
    function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure {
7226
        bytes32 m0;
7227
        bytes32 m1;
7228
        bytes32 m2;
7229
        bytes32 m3;
7230
        bytes32 m4;
7231
        bytes32 m5;
7232
        bytes32 m6;
7233
        /// @solidity memory-safe-assembly
7234
        assembly {
7235
            function writeString(pos, w) {
7236
                let length := 0
7237
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7238
                mstore(pos, length)
7239
                let shift := sub(256, shl(3, length))
7240
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7241
            }
7242
            m0 := mload(0x00)
7243
            m1 := mload(0x20)
7244
            m2 := mload(0x40)
7245
            m3 := mload(0x60)
7246
            m4 := mload(0x80)
7247
            m5 := mload(0xa0)
7248
            m6 := mload(0xc0)
7249
            // Selector of `log(bool,uint256,string,bool)`.
7250
            mstore(0x00, 0xe5e70b2b)
7251
            mstore(0x20, p0)
7252
            mstore(0x40, p1)
7253
            mstore(0x60, 0x80)
7254
            mstore(0x80, p3)
7255
            writeString(0xa0, p2)
7256
        }
7257
        _sendLogPayload(0x1c, 0xc4);
7258
        /// @solidity memory-safe-assembly
7259
        assembly {
7260
            mstore(0x00, m0)
7261
            mstore(0x20, m1)
7262
            mstore(0x40, m2)
7263
            mstore(0x60, m3)
7264
            mstore(0x80, m4)
7265
            mstore(0xa0, m5)
7266
            mstore(0xc0, m6)
7267
        }
7268
    }
7269

                            
                        
7270
    function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
7271
        bytes32 m0;
7272
        bytes32 m1;
7273
        bytes32 m2;
7274
        bytes32 m3;
7275
        bytes32 m4;
7276
        bytes32 m5;
7277
        bytes32 m6;
7278
        /// @solidity memory-safe-assembly
7279
        assembly {
7280
            function writeString(pos, w) {
7281
                let length := 0
7282
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7283
                mstore(pos, length)
7284
                let shift := sub(256, shl(3, length))
7285
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7286
            }
7287
            m0 := mload(0x00)
7288
            m1 := mload(0x20)
7289
            m2 := mload(0x40)
7290
            m3 := mload(0x60)
7291
            m4 := mload(0x80)
7292
            m5 := mload(0xa0)
7293
            m6 := mload(0xc0)
7294
            // Selector of `log(bool,uint256,string,uint256)`.
7295
            mstore(0x00, 0x6a1199e2)
7296
            mstore(0x20, p0)
7297
            mstore(0x40, p1)
7298
            mstore(0x60, 0x80)
7299
            mstore(0x80, p3)
7300
            writeString(0xa0, p2)
7301
        }
7302
        _sendLogPayload(0x1c, 0xc4);
7303
        /// @solidity memory-safe-assembly
7304
        assembly {
7305
            mstore(0x00, m0)
7306
            mstore(0x20, m1)
7307
            mstore(0x40, m2)
7308
            mstore(0x60, m3)
7309
            mstore(0x80, m4)
7310
            mstore(0xa0, m5)
7311
            mstore(0xc0, m6)
7312
        }
7313
    }
7314

                            
                        
7315
    function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
7316
        bytes32 m0;
7317
        bytes32 m1;
7318
        bytes32 m2;
7319
        bytes32 m3;
7320
        bytes32 m4;
7321
        bytes32 m5;
7322
        bytes32 m6;
7323
        bytes32 m7;
7324
        bytes32 m8;
7325
        /// @solidity memory-safe-assembly
7326
        assembly {
7327
            function writeString(pos, w) {
7328
                let length := 0
7329
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7330
                mstore(pos, length)
7331
                let shift := sub(256, shl(3, length))
7332
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7333
            }
7334
            m0 := mload(0x00)
7335
            m1 := mload(0x20)
7336
            m2 := mload(0x40)
7337
            m3 := mload(0x60)
7338
            m4 := mload(0x80)
7339
            m5 := mload(0xa0)
7340
            m6 := mload(0xc0)
7341
            m7 := mload(0xe0)
7342
            m8 := mload(0x100)
7343
            // Selector of `log(bool,uint256,string,string)`.
7344
            mstore(0x00, 0xf5bc2249)
7345
            mstore(0x20, p0)
7346
            mstore(0x40, p1)
7347
            mstore(0x60, 0x80)
7348
            mstore(0x80, 0xc0)
7349
            writeString(0xa0, p2)
7350
            writeString(0xe0, p3)
7351
        }
7352
        _sendLogPayload(0x1c, 0x104);
7353
        /// @solidity memory-safe-assembly
7354
        assembly {
7355
            mstore(0x00, m0)
7356
            mstore(0x20, m1)
7357
            mstore(0x40, m2)
7358
            mstore(0x60, m3)
7359
            mstore(0x80, m4)
7360
            mstore(0xa0, m5)
7361
            mstore(0xc0, m6)
7362
            mstore(0xe0, m7)
7363
            mstore(0x100, m8)
7364
        }
7365
    }
7366

                            
                        
7367
    function log(bool p0, bytes32 p1, address p2, address p3) internal pure {
7368
        bytes32 m0;
7369
        bytes32 m1;
7370
        bytes32 m2;
7371
        bytes32 m3;
7372
        bytes32 m4;
7373
        bytes32 m5;
7374
        bytes32 m6;
7375
        /// @solidity memory-safe-assembly
7376
        assembly {
7377
            function writeString(pos, w) {
7378
                let length := 0
7379
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7380
                mstore(pos, length)
7381
                let shift := sub(256, shl(3, length))
7382
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7383
            }
7384
            m0 := mload(0x00)
7385
            m1 := mload(0x20)
7386
            m2 := mload(0x40)
7387
            m3 := mload(0x60)
7388
            m4 := mload(0x80)
7389
            m5 := mload(0xa0)
7390
            m6 := mload(0xc0)
7391
            // Selector of `log(bool,string,address,address)`.
7392
            mstore(0x00, 0x2b2b18dc)
7393
            mstore(0x20, p0)
7394
            mstore(0x40, 0x80)
7395
            mstore(0x60, p2)
7396
            mstore(0x80, p3)
7397
            writeString(0xa0, p1)
7398
        }
7399
        _sendLogPayload(0x1c, 0xc4);
7400
        /// @solidity memory-safe-assembly
7401
        assembly {
7402
            mstore(0x00, m0)
7403
            mstore(0x20, m1)
7404
            mstore(0x40, m2)
7405
            mstore(0x60, m3)
7406
            mstore(0x80, m4)
7407
            mstore(0xa0, m5)
7408
            mstore(0xc0, m6)
7409
        }
7410
    }
7411

                            
                        
7412
    function log(bool p0, bytes32 p1, address p2, bool p3) internal pure {
7413
        bytes32 m0;
7414
        bytes32 m1;
7415
        bytes32 m2;
7416
        bytes32 m3;
7417
        bytes32 m4;
7418
        bytes32 m5;
7419
        bytes32 m6;
7420
        /// @solidity memory-safe-assembly
7421
        assembly {
7422
            function writeString(pos, w) {
7423
                let length := 0
7424
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7425
                mstore(pos, length)
7426
                let shift := sub(256, shl(3, length))
7427
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7428
            }
7429
            m0 := mload(0x00)
7430
            m1 := mload(0x20)
7431
            m2 := mload(0x40)
7432
            m3 := mload(0x60)
7433
            m4 := mload(0x80)
7434
            m5 := mload(0xa0)
7435
            m6 := mload(0xc0)
7436
            // Selector of `log(bool,string,address,bool)`.
7437
            mstore(0x00, 0x6dd434ca)
7438
            mstore(0x20, p0)
7439
            mstore(0x40, 0x80)
7440
            mstore(0x60, p2)
7441
            mstore(0x80, p3)
7442
            writeString(0xa0, p1)
7443
        }
7444
        _sendLogPayload(0x1c, 0xc4);
7445
        /// @solidity memory-safe-assembly
7446
        assembly {
7447
            mstore(0x00, m0)
7448
            mstore(0x20, m1)
7449
            mstore(0x40, m2)
7450
            mstore(0x60, m3)
7451
            mstore(0x80, m4)
7452
            mstore(0xa0, m5)
7453
            mstore(0xc0, m6)
7454
        }
7455
    }
7456

                            
                        
7457
    function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure {
7458
        bytes32 m0;
7459
        bytes32 m1;
7460
        bytes32 m2;
7461
        bytes32 m3;
7462
        bytes32 m4;
7463
        bytes32 m5;
7464
        bytes32 m6;
7465
        /// @solidity memory-safe-assembly
7466
        assembly {
7467
            function writeString(pos, w) {
7468
                let length := 0
7469
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7470
                mstore(pos, length)
7471
                let shift := sub(256, shl(3, length))
7472
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7473
            }
7474
            m0 := mload(0x00)
7475
            m1 := mload(0x20)
7476
            m2 := mload(0x40)
7477
            m3 := mload(0x60)
7478
            m4 := mload(0x80)
7479
            m5 := mload(0xa0)
7480
            m6 := mload(0xc0)
7481
            // Selector of `log(bool,string,address,uint256)`.
7482
            mstore(0x00, 0xa5cada94)
7483
            mstore(0x20, p0)
7484
            mstore(0x40, 0x80)
7485
            mstore(0x60, p2)
7486
            mstore(0x80, p3)
7487
            writeString(0xa0, p1)
7488
        }
7489
        _sendLogPayload(0x1c, 0xc4);
7490
        /// @solidity memory-safe-assembly
7491
        assembly {
7492
            mstore(0x00, m0)
7493
            mstore(0x20, m1)
7494
            mstore(0x40, m2)
7495
            mstore(0x60, m3)
7496
            mstore(0x80, m4)
7497
            mstore(0xa0, m5)
7498
            mstore(0xc0, m6)
7499
        }
7500
    }
7501

                            
                        
7502
    function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure {
7503
        bytes32 m0;
7504
        bytes32 m1;
7505
        bytes32 m2;
7506
        bytes32 m3;
7507
        bytes32 m4;
7508
        bytes32 m5;
7509
        bytes32 m6;
7510
        bytes32 m7;
7511
        bytes32 m8;
7512
        /// @solidity memory-safe-assembly
7513
        assembly {
7514
            function writeString(pos, w) {
7515
                let length := 0
7516
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7517
                mstore(pos, length)
7518
                let shift := sub(256, shl(3, length))
7519
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7520
            }
7521
            m0 := mload(0x00)
7522
            m1 := mload(0x20)
7523
            m2 := mload(0x40)
7524
            m3 := mload(0x60)
7525
            m4 := mload(0x80)
7526
            m5 := mload(0xa0)
7527
            m6 := mload(0xc0)
7528
            m7 := mload(0xe0)
7529
            m8 := mload(0x100)
7530
            // Selector of `log(bool,string,address,string)`.
7531
            mstore(0x00, 0x12d6c788)
7532
            mstore(0x20, p0)
7533
            mstore(0x40, 0x80)
7534
            mstore(0x60, p2)
7535
            mstore(0x80, 0xc0)
7536
            writeString(0xa0, p1)
7537
            writeString(0xe0, p3)
7538
        }
7539
        _sendLogPayload(0x1c, 0x104);
7540
        /// @solidity memory-safe-assembly
7541
        assembly {
7542
            mstore(0x00, m0)
7543
            mstore(0x20, m1)
7544
            mstore(0x40, m2)
7545
            mstore(0x60, m3)
7546
            mstore(0x80, m4)
7547
            mstore(0xa0, m5)
7548
            mstore(0xc0, m6)
7549
            mstore(0xe0, m7)
7550
            mstore(0x100, m8)
7551
        }
7552
    }
7553

                            
                        
7554
    function log(bool p0, bytes32 p1, bool p2, address p3) internal pure {
7555
        bytes32 m0;
7556
        bytes32 m1;
7557
        bytes32 m2;
7558
        bytes32 m3;
7559
        bytes32 m4;
7560
        bytes32 m5;
7561
        bytes32 m6;
7562
        /// @solidity memory-safe-assembly
7563
        assembly {
7564
            function writeString(pos, w) {
7565
                let length := 0
7566
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7567
                mstore(pos, length)
7568
                let shift := sub(256, shl(3, length))
7569
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7570
            }
7571
            m0 := mload(0x00)
7572
            m1 := mload(0x20)
7573
            m2 := mload(0x40)
7574
            m3 := mload(0x60)
7575
            m4 := mload(0x80)
7576
            m5 := mload(0xa0)
7577
            m6 := mload(0xc0)
7578
            // Selector of `log(bool,string,bool,address)`.
7579
            mstore(0x00, 0x538e06ab)
7580
            mstore(0x20, p0)
7581
            mstore(0x40, 0x80)
7582
            mstore(0x60, p2)
7583
            mstore(0x80, p3)
7584
            writeString(0xa0, p1)
7585
        }
7586
        _sendLogPayload(0x1c, 0xc4);
7587
        /// @solidity memory-safe-assembly
7588
        assembly {
7589
            mstore(0x00, m0)
7590
            mstore(0x20, m1)
7591
            mstore(0x40, m2)
7592
            mstore(0x60, m3)
7593
            mstore(0x80, m4)
7594
            mstore(0xa0, m5)
7595
            mstore(0xc0, m6)
7596
        }
7597
    }
7598

                            
                        
7599
    function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure {
7600
        bytes32 m0;
7601
        bytes32 m1;
7602
        bytes32 m2;
7603
        bytes32 m3;
7604
        bytes32 m4;
7605
        bytes32 m5;
7606
        bytes32 m6;
7607
        /// @solidity memory-safe-assembly
7608
        assembly {
7609
            function writeString(pos, w) {
7610
                let length := 0
7611
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7612
                mstore(pos, length)
7613
                let shift := sub(256, shl(3, length))
7614
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7615
            }
7616
            m0 := mload(0x00)
7617
            m1 := mload(0x20)
7618
            m2 := mload(0x40)
7619
            m3 := mload(0x60)
7620
            m4 := mload(0x80)
7621
            m5 := mload(0xa0)
7622
            m6 := mload(0xc0)
7623
            // Selector of `log(bool,string,bool,bool)`.
7624
            mstore(0x00, 0xdc5e935b)
7625
            mstore(0x20, p0)
7626
            mstore(0x40, 0x80)
7627
            mstore(0x60, p2)
7628
            mstore(0x80, p3)
7629
            writeString(0xa0, p1)
7630
        }
7631
        _sendLogPayload(0x1c, 0xc4);
7632
        /// @solidity memory-safe-assembly
7633
        assembly {
7634
            mstore(0x00, m0)
7635
            mstore(0x20, m1)
7636
            mstore(0x40, m2)
7637
            mstore(0x60, m3)
7638
            mstore(0x80, m4)
7639
            mstore(0xa0, m5)
7640
            mstore(0xc0, m6)
7641
        }
7642
    }
7643

                            
                        
7644
    function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure {
7645
        bytes32 m0;
7646
        bytes32 m1;
7647
        bytes32 m2;
7648
        bytes32 m3;
7649
        bytes32 m4;
7650
        bytes32 m5;
7651
        bytes32 m6;
7652
        /// @solidity memory-safe-assembly
7653
        assembly {
7654
            function writeString(pos, w) {
7655
                let length := 0
7656
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7657
                mstore(pos, length)
7658
                let shift := sub(256, shl(3, length))
7659
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7660
            }
7661
            m0 := mload(0x00)
7662
            m1 := mload(0x20)
7663
            m2 := mload(0x40)
7664
            m3 := mload(0x60)
7665
            m4 := mload(0x80)
7666
            m5 := mload(0xa0)
7667
            m6 := mload(0xc0)
7668
            // Selector of `log(bool,string,bool,uint256)`.
7669
            mstore(0x00, 0x1606a393)
7670
            mstore(0x20, p0)
7671
            mstore(0x40, 0x80)
7672
            mstore(0x60, p2)
7673
            mstore(0x80, p3)
7674
            writeString(0xa0, p1)
7675
        }
7676
        _sendLogPayload(0x1c, 0xc4);
7677
        /// @solidity memory-safe-assembly
7678
        assembly {
7679
            mstore(0x00, m0)
7680
            mstore(0x20, m1)
7681
            mstore(0x40, m2)
7682
            mstore(0x60, m3)
7683
            mstore(0x80, m4)
7684
            mstore(0xa0, m5)
7685
            mstore(0xc0, m6)
7686
        }
7687
    }
7688

                            
                        
7689
    function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
7690
        bytes32 m0;
7691
        bytes32 m1;
7692
        bytes32 m2;
7693
        bytes32 m3;
7694
        bytes32 m4;
7695
        bytes32 m5;
7696
        bytes32 m6;
7697
        bytes32 m7;
7698
        bytes32 m8;
7699
        /// @solidity memory-safe-assembly
7700
        assembly {
7701
            function writeString(pos, w) {
7702
                let length := 0
7703
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7704
                mstore(pos, length)
7705
                let shift := sub(256, shl(3, length))
7706
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7707
            }
7708
            m0 := mload(0x00)
7709
            m1 := mload(0x20)
7710
            m2 := mload(0x40)
7711
            m3 := mload(0x60)
7712
            m4 := mload(0x80)
7713
            m5 := mload(0xa0)
7714
            m6 := mload(0xc0)
7715
            m7 := mload(0xe0)
7716
            m8 := mload(0x100)
7717
            // Selector of `log(bool,string,bool,string)`.
7718
            mstore(0x00, 0x483d0416)
7719
            mstore(0x20, p0)
7720
            mstore(0x40, 0x80)
7721
            mstore(0x60, p2)
7722
            mstore(0x80, 0xc0)
7723
            writeString(0xa0, p1)
7724
            writeString(0xe0, p3)
7725
        }
7726
        _sendLogPayload(0x1c, 0x104);
7727
        /// @solidity memory-safe-assembly
7728
        assembly {
7729
            mstore(0x00, m0)
7730
            mstore(0x20, m1)
7731
            mstore(0x40, m2)
7732
            mstore(0x60, m3)
7733
            mstore(0x80, m4)
7734
            mstore(0xa0, m5)
7735
            mstore(0xc0, m6)
7736
            mstore(0xe0, m7)
7737
            mstore(0x100, m8)
7738
        }
7739
    }
7740

                            
                        
7741
    function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure {
7742
        bytes32 m0;
7743
        bytes32 m1;
7744
        bytes32 m2;
7745
        bytes32 m3;
7746
        bytes32 m4;
7747
        bytes32 m5;
7748
        bytes32 m6;
7749
        /// @solidity memory-safe-assembly
7750
        assembly {
7751
            function writeString(pos, w) {
7752
                let length := 0
7753
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7754
                mstore(pos, length)
7755
                let shift := sub(256, shl(3, length))
7756
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7757
            }
7758
            m0 := mload(0x00)
7759
            m1 := mload(0x20)
7760
            m2 := mload(0x40)
7761
            m3 := mload(0x60)
7762
            m4 := mload(0x80)
7763
            m5 := mload(0xa0)
7764
            m6 := mload(0xc0)
7765
            // Selector of `log(bool,string,uint256,address)`.
7766
            mstore(0x00, 0x1596a1ce)
7767
            mstore(0x20, p0)
7768
            mstore(0x40, 0x80)
7769
            mstore(0x60, p2)
7770
            mstore(0x80, p3)
7771
            writeString(0xa0, p1)
7772
        }
7773
        _sendLogPayload(0x1c, 0xc4);
7774
        /// @solidity memory-safe-assembly
7775
        assembly {
7776
            mstore(0x00, m0)
7777
            mstore(0x20, m1)
7778
            mstore(0x40, m2)
7779
            mstore(0x60, m3)
7780
            mstore(0x80, m4)
7781
            mstore(0xa0, m5)
7782
            mstore(0xc0, m6)
7783
        }
7784
    }
7785

                            
                        
7786
    function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure {
7787
        bytes32 m0;
7788
        bytes32 m1;
7789
        bytes32 m2;
7790
        bytes32 m3;
7791
        bytes32 m4;
7792
        bytes32 m5;
7793
        bytes32 m6;
7794
        /// @solidity memory-safe-assembly
7795
        assembly {
7796
            function writeString(pos, w) {
7797
                let length := 0
7798
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7799
                mstore(pos, length)
7800
                let shift := sub(256, shl(3, length))
7801
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7802
            }
7803
            m0 := mload(0x00)
7804
            m1 := mload(0x20)
7805
            m2 := mload(0x40)
7806
            m3 := mload(0x60)
7807
            m4 := mload(0x80)
7808
            m5 := mload(0xa0)
7809
            m6 := mload(0xc0)
7810
            // Selector of `log(bool,string,uint256,bool)`.
7811
            mstore(0x00, 0x6b0e5d53)
7812
            mstore(0x20, p0)
7813
            mstore(0x40, 0x80)
7814
            mstore(0x60, p2)
7815
            mstore(0x80, p3)
7816
            writeString(0xa0, p1)
7817
        }
7818
        _sendLogPayload(0x1c, 0xc4);
7819
        /// @solidity memory-safe-assembly
7820
        assembly {
7821
            mstore(0x00, m0)
7822
            mstore(0x20, m1)
7823
            mstore(0x40, m2)
7824
            mstore(0x60, m3)
7825
            mstore(0x80, m4)
7826
            mstore(0xa0, m5)
7827
            mstore(0xc0, m6)
7828
        }
7829
    }
7830

                            
                        
7831
    function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
7832
        bytes32 m0;
7833
        bytes32 m1;
7834
        bytes32 m2;
7835
        bytes32 m3;
7836
        bytes32 m4;
7837
        bytes32 m5;
7838
        bytes32 m6;
7839
        /// @solidity memory-safe-assembly
7840
        assembly {
7841
            function writeString(pos, w) {
7842
                let length := 0
7843
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7844
                mstore(pos, length)
7845
                let shift := sub(256, shl(3, length))
7846
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7847
            }
7848
            m0 := mload(0x00)
7849
            m1 := mload(0x20)
7850
            m2 := mload(0x40)
7851
            m3 := mload(0x60)
7852
            m4 := mload(0x80)
7853
            m5 := mload(0xa0)
7854
            m6 := mload(0xc0)
7855
            // Selector of `log(bool,string,uint256,uint256)`.
7856
            mstore(0x00, 0x28863fcb)
7857
            mstore(0x20, p0)
7858
            mstore(0x40, 0x80)
7859
            mstore(0x60, p2)
7860
            mstore(0x80, p3)
7861
            writeString(0xa0, p1)
7862
        }
7863
        _sendLogPayload(0x1c, 0xc4);
7864
        /// @solidity memory-safe-assembly
7865
        assembly {
7866
            mstore(0x00, m0)
7867
            mstore(0x20, m1)
7868
            mstore(0x40, m2)
7869
            mstore(0x60, m3)
7870
            mstore(0x80, m4)
7871
            mstore(0xa0, m5)
7872
            mstore(0xc0, m6)
7873
        }
7874
    }
7875

                            
                        
7876
    function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
7877
        bytes32 m0;
7878
        bytes32 m1;
7879
        bytes32 m2;
7880
        bytes32 m3;
7881
        bytes32 m4;
7882
        bytes32 m5;
7883
        bytes32 m6;
7884
        bytes32 m7;
7885
        bytes32 m8;
7886
        /// @solidity memory-safe-assembly
7887
        assembly {
7888
            function writeString(pos, w) {
7889
                let length := 0
7890
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7891
                mstore(pos, length)
7892
                let shift := sub(256, shl(3, length))
7893
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7894
            }
7895
            m0 := mload(0x00)
7896
            m1 := mload(0x20)
7897
            m2 := mload(0x40)
7898
            m3 := mload(0x60)
7899
            m4 := mload(0x80)
7900
            m5 := mload(0xa0)
7901
            m6 := mload(0xc0)
7902
            m7 := mload(0xe0)
7903
            m8 := mload(0x100)
7904
            // Selector of `log(bool,string,uint256,string)`.
7905
            mstore(0x00, 0x1ad96de6)
7906
            mstore(0x20, p0)
7907
            mstore(0x40, 0x80)
7908
            mstore(0x60, p2)
7909
            mstore(0x80, 0xc0)
7910
            writeString(0xa0, p1)
7911
            writeString(0xe0, p3)
7912
        }
7913
        _sendLogPayload(0x1c, 0x104);
7914
        /// @solidity memory-safe-assembly
7915
        assembly {
7916
            mstore(0x00, m0)
7917
            mstore(0x20, m1)
7918
            mstore(0x40, m2)
7919
            mstore(0x60, m3)
7920
            mstore(0x80, m4)
7921
            mstore(0xa0, m5)
7922
            mstore(0xc0, m6)
7923
            mstore(0xe0, m7)
7924
            mstore(0x100, m8)
7925
        }
7926
    }
7927

                            
                        
7928
    function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure {
7929
        bytes32 m0;
7930
        bytes32 m1;
7931
        bytes32 m2;
7932
        bytes32 m3;
7933
        bytes32 m4;
7934
        bytes32 m5;
7935
        bytes32 m6;
7936
        bytes32 m7;
7937
        bytes32 m8;
7938
        /// @solidity memory-safe-assembly
7939
        assembly {
7940
            function writeString(pos, w) {
7941
                let length := 0
7942
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7943
                mstore(pos, length)
7944
                let shift := sub(256, shl(3, length))
7945
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7946
            }
7947
            m0 := mload(0x00)
7948
            m1 := mload(0x20)
7949
            m2 := mload(0x40)
7950
            m3 := mload(0x60)
7951
            m4 := mload(0x80)
7952
            m5 := mload(0xa0)
7953
            m6 := mload(0xc0)
7954
            m7 := mload(0xe0)
7955
            m8 := mload(0x100)
7956
            // Selector of `log(bool,string,string,address)`.
7957
            mstore(0x00, 0x97d394d8)
7958
            mstore(0x20, p0)
7959
            mstore(0x40, 0x80)
7960
            mstore(0x60, 0xc0)
7961
            mstore(0x80, p3)
7962
            writeString(0xa0, p1)
7963
            writeString(0xe0, p2)
7964
        }
7965
        _sendLogPayload(0x1c, 0x104);
7966
        /// @solidity memory-safe-assembly
7967
        assembly {
7968
            mstore(0x00, m0)
7969
            mstore(0x20, m1)
7970
            mstore(0x40, m2)
7971
            mstore(0x60, m3)
7972
            mstore(0x80, m4)
7973
            mstore(0xa0, m5)
7974
            mstore(0xc0, m6)
7975
            mstore(0xe0, m7)
7976
            mstore(0x100, m8)
7977
        }
7978
    }
7979

                            
                        
7980
    function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
7981
        bytes32 m0;
7982
        bytes32 m1;
7983
        bytes32 m2;
7984
        bytes32 m3;
7985
        bytes32 m4;
7986
        bytes32 m5;
7987
        bytes32 m6;
7988
        bytes32 m7;
7989
        bytes32 m8;
7990
        /// @solidity memory-safe-assembly
7991
        assembly {
7992
            function writeString(pos, w) {
7993
                let length := 0
7994
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
7995
                mstore(pos, length)
7996
                let shift := sub(256, shl(3, length))
7997
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
7998
            }
7999
            m0 := mload(0x00)
8000
            m1 := mload(0x20)
8001
            m2 := mload(0x40)
8002
            m3 := mload(0x60)
8003
            m4 := mload(0x80)
8004
            m5 := mload(0xa0)
8005
            m6 := mload(0xc0)
8006
            m7 := mload(0xe0)
8007
            m8 := mload(0x100)
8008
            // Selector of `log(bool,string,string,bool)`.
8009
            mstore(0x00, 0x1e4b87e5)
8010
            mstore(0x20, p0)
8011
            mstore(0x40, 0x80)
8012
            mstore(0x60, 0xc0)
8013
            mstore(0x80, p3)
8014
            writeString(0xa0, p1)
8015
            writeString(0xe0, p2)
8016
        }
8017
        _sendLogPayload(0x1c, 0x104);
8018
        /// @solidity memory-safe-assembly
8019
        assembly {
8020
            mstore(0x00, m0)
8021
            mstore(0x20, m1)
8022
            mstore(0x40, m2)
8023
            mstore(0x60, m3)
8024
            mstore(0x80, m4)
8025
            mstore(0xa0, m5)
8026
            mstore(0xc0, m6)
8027
            mstore(0xe0, m7)
8028
            mstore(0x100, m8)
8029
        }
8030
    }
8031

                            
                        
8032
    function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
8033
        bytes32 m0;
8034
        bytes32 m1;
8035
        bytes32 m2;
8036
        bytes32 m3;
8037
        bytes32 m4;
8038
        bytes32 m5;
8039
        bytes32 m6;
8040
        bytes32 m7;
8041
        bytes32 m8;
8042
        /// @solidity memory-safe-assembly
8043
        assembly {
8044
            function writeString(pos, w) {
8045
                let length := 0
8046
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8047
                mstore(pos, length)
8048
                let shift := sub(256, shl(3, length))
8049
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8050
            }
8051
            m0 := mload(0x00)
8052
            m1 := mload(0x20)
8053
            m2 := mload(0x40)
8054
            m3 := mload(0x60)
8055
            m4 := mload(0x80)
8056
            m5 := mload(0xa0)
8057
            m6 := mload(0xc0)
8058
            m7 := mload(0xe0)
8059
            m8 := mload(0x100)
8060
            // Selector of `log(bool,string,string,uint256)`.
8061
            mstore(0x00, 0x7be0c3eb)
8062
            mstore(0x20, p0)
8063
            mstore(0x40, 0x80)
8064
            mstore(0x60, 0xc0)
8065
            mstore(0x80, p3)
8066
            writeString(0xa0, p1)
8067
            writeString(0xe0, p2)
8068
        }
8069
        _sendLogPayload(0x1c, 0x104);
8070
        /// @solidity memory-safe-assembly
8071
        assembly {
8072
            mstore(0x00, m0)
8073
            mstore(0x20, m1)
8074
            mstore(0x40, m2)
8075
            mstore(0x60, m3)
8076
            mstore(0x80, m4)
8077
            mstore(0xa0, m5)
8078
            mstore(0xc0, m6)
8079
            mstore(0xe0, m7)
8080
            mstore(0x100, m8)
8081
        }
8082
    }
8083

                            
                        
8084
    function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
8085
        bytes32 m0;
8086
        bytes32 m1;
8087
        bytes32 m2;
8088
        bytes32 m3;
8089
        bytes32 m4;
8090
        bytes32 m5;
8091
        bytes32 m6;
8092
        bytes32 m7;
8093
        bytes32 m8;
8094
        bytes32 m9;
8095
        bytes32 m10;
8096
        /// @solidity memory-safe-assembly
8097
        assembly {
8098
            function writeString(pos, w) {
8099
                let length := 0
8100
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8101
                mstore(pos, length)
8102
                let shift := sub(256, shl(3, length))
8103
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8104
            }
8105
            m0 := mload(0x00)
8106
            m1 := mload(0x20)
8107
            m2 := mload(0x40)
8108
            m3 := mload(0x60)
8109
            m4 := mload(0x80)
8110
            m5 := mload(0xa0)
8111
            m6 := mload(0xc0)
8112
            m7 := mload(0xe0)
8113
            m8 := mload(0x100)
8114
            m9 := mload(0x120)
8115
            m10 := mload(0x140)
8116
            // Selector of `log(bool,string,string,string)`.
8117
            mstore(0x00, 0x1762e32a)
8118
            mstore(0x20, p0)
8119
            mstore(0x40, 0x80)
8120
            mstore(0x60, 0xc0)
8121
            mstore(0x80, 0x100)
8122
            writeString(0xa0, p1)
8123
            writeString(0xe0, p2)
8124
            writeString(0x120, p3)
8125
        }
8126
        _sendLogPayload(0x1c, 0x144);
8127
        /// @solidity memory-safe-assembly
8128
        assembly {
8129
            mstore(0x00, m0)
8130
            mstore(0x20, m1)
8131
            mstore(0x40, m2)
8132
            mstore(0x60, m3)
8133
            mstore(0x80, m4)
8134
            mstore(0xa0, m5)
8135
            mstore(0xc0, m6)
8136
            mstore(0xe0, m7)
8137
            mstore(0x100, m8)
8138
            mstore(0x120, m9)
8139
            mstore(0x140, m10)
8140
        }
8141
    }
8142

                            
                        
8143
    function log(uint256 p0, address p1, address p2, address p3) internal pure {
8144
        bytes32 m0;
8145
        bytes32 m1;
8146
        bytes32 m2;
8147
        bytes32 m3;
8148
        bytes32 m4;
8149
        /// @solidity memory-safe-assembly
8150
        assembly {
8151
            m0 := mload(0x00)
8152
            m1 := mload(0x20)
8153
            m2 := mload(0x40)
8154
            m3 := mload(0x60)
8155
            m4 := mload(0x80)
8156
            // Selector of `log(uint256,address,address,address)`.
8157
            mstore(0x00, 0x2488b414)
8158
            mstore(0x20, p0)
8159
            mstore(0x40, p1)
8160
            mstore(0x60, p2)
8161
            mstore(0x80, p3)
8162
        }
8163
        _sendLogPayload(0x1c, 0x84);
8164
        /// @solidity memory-safe-assembly
8165
        assembly {
8166
            mstore(0x00, m0)
8167
            mstore(0x20, m1)
8168
            mstore(0x40, m2)
8169
            mstore(0x60, m3)
8170
            mstore(0x80, m4)
8171
        }
8172
    }
8173

                            
                        
8174
    function log(uint256 p0, address p1, address p2, bool p3) internal pure {
8175
        bytes32 m0;
8176
        bytes32 m1;
8177
        bytes32 m2;
8178
        bytes32 m3;
8179
        bytes32 m4;
8180
        /// @solidity memory-safe-assembly
8181
        assembly {
8182
            m0 := mload(0x00)
8183
            m1 := mload(0x20)
8184
            m2 := mload(0x40)
8185
            m3 := mload(0x60)
8186
            m4 := mload(0x80)
8187
            // Selector of `log(uint256,address,address,bool)`.
8188
            mstore(0x00, 0x091ffaf5)
8189
            mstore(0x20, p0)
8190
            mstore(0x40, p1)
8191
            mstore(0x60, p2)
8192
            mstore(0x80, p3)
8193
        }
8194
        _sendLogPayload(0x1c, 0x84);
8195
        /// @solidity memory-safe-assembly
8196
        assembly {
8197
            mstore(0x00, m0)
8198
            mstore(0x20, m1)
8199
            mstore(0x40, m2)
8200
            mstore(0x60, m3)
8201
            mstore(0x80, m4)
8202
        }
8203
    }
8204

                            
                        
8205
    function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
8206
        bytes32 m0;
8207
        bytes32 m1;
8208
        bytes32 m2;
8209
        bytes32 m3;
8210
        bytes32 m4;
8211
        /// @solidity memory-safe-assembly
8212
        assembly {
8213
            m0 := mload(0x00)
8214
            m1 := mload(0x20)
8215
            m2 := mload(0x40)
8216
            m3 := mload(0x60)
8217
            m4 := mload(0x80)
8218
            // Selector of `log(uint256,address,address,uint256)`.
8219
            mstore(0x00, 0x736efbb6)
8220
            mstore(0x20, p0)
8221
            mstore(0x40, p1)
8222
            mstore(0x60, p2)
8223
            mstore(0x80, p3)
8224
        }
8225
        _sendLogPayload(0x1c, 0x84);
8226
        /// @solidity memory-safe-assembly
8227
        assembly {
8228
            mstore(0x00, m0)
8229
            mstore(0x20, m1)
8230
            mstore(0x40, m2)
8231
            mstore(0x60, m3)
8232
            mstore(0x80, m4)
8233
        }
8234
    }
8235

                            
                        
8236
    function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure {
8237
        bytes32 m0;
8238
        bytes32 m1;
8239
        bytes32 m2;
8240
        bytes32 m3;
8241
        bytes32 m4;
8242
        bytes32 m5;
8243
        bytes32 m6;
8244
        /// @solidity memory-safe-assembly
8245
        assembly {
8246
            function writeString(pos, w) {
8247
                let length := 0
8248
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8249
                mstore(pos, length)
8250
                let shift := sub(256, shl(3, length))
8251
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8252
            }
8253
            m0 := mload(0x00)
8254
            m1 := mload(0x20)
8255
            m2 := mload(0x40)
8256
            m3 := mload(0x60)
8257
            m4 := mload(0x80)
8258
            m5 := mload(0xa0)
8259
            m6 := mload(0xc0)
8260
            // Selector of `log(uint256,address,address,string)`.
8261
            mstore(0x00, 0x031c6f73)
8262
            mstore(0x20, p0)
8263
            mstore(0x40, p1)
8264
            mstore(0x60, p2)
8265
            mstore(0x80, 0x80)
8266
            writeString(0xa0, p3)
8267
        }
8268
        _sendLogPayload(0x1c, 0xc4);
8269
        /// @solidity memory-safe-assembly
8270
        assembly {
8271
            mstore(0x00, m0)
8272
            mstore(0x20, m1)
8273
            mstore(0x40, m2)
8274
            mstore(0x60, m3)
8275
            mstore(0x80, m4)
8276
            mstore(0xa0, m5)
8277
            mstore(0xc0, m6)
8278
        }
8279
    }
8280

                            
                        
8281
    function log(uint256 p0, address p1, bool p2, address p3) internal pure {
8282
        bytes32 m0;
8283
        bytes32 m1;
8284
        bytes32 m2;
8285
        bytes32 m3;
8286
        bytes32 m4;
8287
        /// @solidity memory-safe-assembly
8288
        assembly {
8289
            m0 := mload(0x00)
8290
            m1 := mload(0x20)
8291
            m2 := mload(0x40)
8292
            m3 := mload(0x60)
8293
            m4 := mload(0x80)
8294
            // Selector of `log(uint256,address,bool,address)`.
8295
            mstore(0x00, 0xef72c513)
8296
            mstore(0x20, p0)
8297
            mstore(0x40, p1)
8298
            mstore(0x60, p2)
8299
            mstore(0x80, p3)
8300
        }
8301
        _sendLogPayload(0x1c, 0x84);
8302
        /// @solidity memory-safe-assembly
8303
        assembly {
8304
            mstore(0x00, m0)
8305
            mstore(0x20, m1)
8306
            mstore(0x40, m2)
8307
            mstore(0x60, m3)
8308
            mstore(0x80, m4)
8309
        }
8310
    }
8311

                            
                        
8312
    function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
8313
        bytes32 m0;
8314
        bytes32 m1;
8315
        bytes32 m2;
8316
        bytes32 m3;
8317
        bytes32 m4;
8318
        /// @solidity memory-safe-assembly
8319
        assembly {
8320
            m0 := mload(0x00)
8321
            m1 := mload(0x20)
8322
            m2 := mload(0x40)
8323
            m3 := mload(0x60)
8324
            m4 := mload(0x80)
8325
            // Selector of `log(uint256,address,bool,bool)`.
8326
            mstore(0x00, 0xe351140f)
8327
            mstore(0x20, p0)
8328
            mstore(0x40, p1)
8329
            mstore(0x60, p2)
8330
            mstore(0x80, p3)
8331
        }
8332
        _sendLogPayload(0x1c, 0x84);
8333
        /// @solidity memory-safe-assembly
8334
        assembly {
8335
            mstore(0x00, m0)
8336
            mstore(0x20, m1)
8337
            mstore(0x40, m2)
8338
            mstore(0x60, m3)
8339
            mstore(0x80, m4)
8340
        }
8341
    }
8342

                            
                        
8343
    function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
8344
        bytes32 m0;
8345
        bytes32 m1;
8346
        bytes32 m2;
8347
        bytes32 m3;
8348
        bytes32 m4;
8349
        /// @solidity memory-safe-assembly
8350
        assembly {
8351
            m0 := mload(0x00)
8352
            m1 := mload(0x20)
8353
            m2 := mload(0x40)
8354
            m3 := mload(0x60)
8355
            m4 := mload(0x80)
8356
            // Selector of `log(uint256,address,bool,uint256)`.
8357
            mstore(0x00, 0x5abd992a)
8358
            mstore(0x20, p0)
8359
            mstore(0x40, p1)
8360
            mstore(0x60, p2)
8361
            mstore(0x80, p3)
8362
        }
8363
        _sendLogPayload(0x1c, 0x84);
8364
        /// @solidity memory-safe-assembly
8365
        assembly {
8366
            mstore(0x00, m0)
8367
            mstore(0x20, m1)
8368
            mstore(0x40, m2)
8369
            mstore(0x60, m3)
8370
            mstore(0x80, m4)
8371
        }
8372
    }
8373

                            
                        
8374
    function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure {
8375
        bytes32 m0;
8376
        bytes32 m1;
8377
        bytes32 m2;
8378
        bytes32 m3;
8379
        bytes32 m4;
8380
        bytes32 m5;
8381
        bytes32 m6;
8382
        /// @solidity memory-safe-assembly
8383
        assembly {
8384
            function writeString(pos, w) {
8385
                let length := 0
8386
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8387
                mstore(pos, length)
8388
                let shift := sub(256, shl(3, length))
8389
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8390
            }
8391
            m0 := mload(0x00)
8392
            m1 := mload(0x20)
8393
            m2 := mload(0x40)
8394
            m3 := mload(0x60)
8395
            m4 := mload(0x80)
8396
            m5 := mload(0xa0)
8397
            m6 := mload(0xc0)
8398
            // Selector of `log(uint256,address,bool,string)`.
8399
            mstore(0x00, 0x90fb06aa)
8400
            mstore(0x20, p0)
8401
            mstore(0x40, p1)
8402
            mstore(0x60, p2)
8403
            mstore(0x80, 0x80)
8404
            writeString(0xa0, p3)
8405
        }
8406
        _sendLogPayload(0x1c, 0xc4);
8407
        /// @solidity memory-safe-assembly
8408
        assembly {
8409
            mstore(0x00, m0)
8410
            mstore(0x20, m1)
8411
            mstore(0x40, m2)
8412
            mstore(0x60, m3)
8413
            mstore(0x80, m4)
8414
            mstore(0xa0, m5)
8415
            mstore(0xc0, m6)
8416
        }
8417
    }
8418

                            
                        
8419
    function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
8420
        bytes32 m0;
8421
        bytes32 m1;
8422
        bytes32 m2;
8423
        bytes32 m3;
8424
        bytes32 m4;
8425
        /// @solidity memory-safe-assembly
8426
        assembly {
8427
            m0 := mload(0x00)
8428
            m1 := mload(0x20)
8429
            m2 := mload(0x40)
8430
            m3 := mload(0x60)
8431
            m4 := mload(0x80)
8432
            // Selector of `log(uint256,address,uint256,address)`.
8433
            mstore(0x00, 0x15c127b5)
8434
            mstore(0x20, p0)
8435
            mstore(0x40, p1)
8436
            mstore(0x60, p2)
8437
            mstore(0x80, p3)
8438
        }
8439
        _sendLogPayload(0x1c, 0x84);
8440
        /// @solidity memory-safe-assembly
8441
        assembly {
8442
            mstore(0x00, m0)
8443
            mstore(0x20, m1)
8444
            mstore(0x40, m2)
8445
            mstore(0x60, m3)
8446
            mstore(0x80, m4)
8447
        }
8448
    }
8449

                            
                        
8450
    function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
8451
        bytes32 m0;
8452
        bytes32 m1;
8453
        bytes32 m2;
8454
        bytes32 m3;
8455
        bytes32 m4;
8456
        /// @solidity memory-safe-assembly
8457
        assembly {
8458
            m0 := mload(0x00)
8459
            m1 := mload(0x20)
8460
            m2 := mload(0x40)
8461
            m3 := mload(0x60)
8462
            m4 := mload(0x80)
8463
            // Selector of `log(uint256,address,uint256,bool)`.
8464
            mstore(0x00, 0x5f743a7c)
8465
            mstore(0x20, p0)
8466
            mstore(0x40, p1)
8467
            mstore(0x60, p2)
8468
            mstore(0x80, p3)
8469
        }
8470
        _sendLogPayload(0x1c, 0x84);
8471
        /// @solidity memory-safe-assembly
8472
        assembly {
8473
            mstore(0x00, m0)
8474
            mstore(0x20, m1)
8475
            mstore(0x40, m2)
8476
            mstore(0x60, m3)
8477
            mstore(0x80, m4)
8478
        }
8479
    }
8480

                            
                        
8481
    function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
8482
        bytes32 m0;
8483
        bytes32 m1;
8484
        bytes32 m2;
8485
        bytes32 m3;
8486
        bytes32 m4;
8487
        /// @solidity memory-safe-assembly
8488
        assembly {
8489
            m0 := mload(0x00)
8490
            m1 := mload(0x20)
8491
            m2 := mload(0x40)
8492
            m3 := mload(0x60)
8493
            m4 := mload(0x80)
8494
            // Selector of `log(uint256,address,uint256,uint256)`.
8495
            mstore(0x00, 0x0c9cd9c1)
8496
            mstore(0x20, p0)
8497
            mstore(0x40, p1)
8498
            mstore(0x60, p2)
8499
            mstore(0x80, p3)
8500
        }
8501
        _sendLogPayload(0x1c, 0x84);
8502
        /// @solidity memory-safe-assembly
8503
        assembly {
8504
            mstore(0x00, m0)
8505
            mstore(0x20, m1)
8506
            mstore(0x40, m2)
8507
            mstore(0x60, m3)
8508
            mstore(0x80, m4)
8509
        }
8510
    }
8511

                            
                        
8512
    function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure {
8513
        bytes32 m0;
8514
        bytes32 m1;
8515
        bytes32 m2;
8516
        bytes32 m3;
8517
        bytes32 m4;
8518
        bytes32 m5;
8519
        bytes32 m6;
8520
        /// @solidity memory-safe-assembly
8521
        assembly {
8522
            function writeString(pos, w) {
8523
                let length := 0
8524
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8525
                mstore(pos, length)
8526
                let shift := sub(256, shl(3, length))
8527
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8528
            }
8529
            m0 := mload(0x00)
8530
            m1 := mload(0x20)
8531
            m2 := mload(0x40)
8532
            m3 := mload(0x60)
8533
            m4 := mload(0x80)
8534
            m5 := mload(0xa0)
8535
            m6 := mload(0xc0)
8536
            // Selector of `log(uint256,address,uint256,string)`.
8537
            mstore(0x00, 0xddb06521)
8538
            mstore(0x20, p0)
8539
            mstore(0x40, p1)
8540
            mstore(0x60, p2)
8541
            mstore(0x80, 0x80)
8542
            writeString(0xa0, p3)
8543
        }
8544
        _sendLogPayload(0x1c, 0xc4);
8545
        /// @solidity memory-safe-assembly
8546
        assembly {
8547
            mstore(0x00, m0)
8548
            mstore(0x20, m1)
8549
            mstore(0x40, m2)
8550
            mstore(0x60, m3)
8551
            mstore(0x80, m4)
8552
            mstore(0xa0, m5)
8553
            mstore(0xc0, m6)
8554
        }
8555
    }
8556

                            
                        
8557
    function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure {
8558
        bytes32 m0;
8559
        bytes32 m1;
8560
        bytes32 m2;
8561
        bytes32 m3;
8562
        bytes32 m4;
8563
        bytes32 m5;
8564
        bytes32 m6;
8565
        /// @solidity memory-safe-assembly
8566
        assembly {
8567
            function writeString(pos, w) {
8568
                let length := 0
8569
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8570
                mstore(pos, length)
8571
                let shift := sub(256, shl(3, length))
8572
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8573
            }
8574
            m0 := mload(0x00)
8575
            m1 := mload(0x20)
8576
            m2 := mload(0x40)
8577
            m3 := mload(0x60)
8578
            m4 := mload(0x80)
8579
            m5 := mload(0xa0)
8580
            m6 := mload(0xc0)
8581
            // Selector of `log(uint256,address,string,address)`.
8582
            mstore(0x00, 0x9cba8fff)
8583
            mstore(0x20, p0)
8584
            mstore(0x40, p1)
8585
            mstore(0x60, 0x80)
8586
            mstore(0x80, p3)
8587
            writeString(0xa0, p2)
8588
        }
8589
        _sendLogPayload(0x1c, 0xc4);
8590
        /// @solidity memory-safe-assembly
8591
        assembly {
8592
            mstore(0x00, m0)
8593
            mstore(0x20, m1)
8594
            mstore(0x40, m2)
8595
            mstore(0x60, m3)
8596
            mstore(0x80, m4)
8597
            mstore(0xa0, m5)
8598
            mstore(0xc0, m6)
8599
        }
8600
    }
8601

                            
                        
8602
    function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure {
8603
        bytes32 m0;
8604
        bytes32 m1;
8605
        bytes32 m2;
8606
        bytes32 m3;
8607
        bytes32 m4;
8608
        bytes32 m5;
8609
        bytes32 m6;
8610
        /// @solidity memory-safe-assembly
8611
        assembly {
8612
            function writeString(pos, w) {
8613
                let length := 0
8614
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8615
                mstore(pos, length)
8616
                let shift := sub(256, shl(3, length))
8617
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8618
            }
8619
            m0 := mload(0x00)
8620
            m1 := mload(0x20)
8621
            m2 := mload(0x40)
8622
            m3 := mload(0x60)
8623
            m4 := mload(0x80)
8624
            m5 := mload(0xa0)
8625
            m6 := mload(0xc0)
8626
            // Selector of `log(uint256,address,string,bool)`.
8627
            mstore(0x00, 0xcc32ab07)
8628
            mstore(0x20, p0)
8629
            mstore(0x40, p1)
8630
            mstore(0x60, 0x80)
8631
            mstore(0x80, p3)
8632
            writeString(0xa0, p2)
8633
        }
8634
        _sendLogPayload(0x1c, 0xc4);
8635
        /// @solidity memory-safe-assembly
8636
        assembly {
8637
            mstore(0x00, m0)
8638
            mstore(0x20, m1)
8639
            mstore(0x40, m2)
8640
            mstore(0x60, m3)
8641
            mstore(0x80, m4)
8642
            mstore(0xa0, m5)
8643
            mstore(0xc0, m6)
8644
        }
8645
    }
8646

                            
                        
8647
    function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure {
8648
        bytes32 m0;
8649
        bytes32 m1;
8650
        bytes32 m2;
8651
        bytes32 m3;
8652
        bytes32 m4;
8653
        bytes32 m5;
8654
        bytes32 m6;
8655
        /// @solidity memory-safe-assembly
8656
        assembly {
8657
            function writeString(pos, w) {
8658
                let length := 0
8659
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8660
                mstore(pos, length)
8661
                let shift := sub(256, shl(3, length))
8662
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8663
            }
8664
            m0 := mload(0x00)
8665
            m1 := mload(0x20)
8666
            m2 := mload(0x40)
8667
            m3 := mload(0x60)
8668
            m4 := mload(0x80)
8669
            m5 := mload(0xa0)
8670
            m6 := mload(0xc0)
8671
            // Selector of `log(uint256,address,string,uint256)`.
8672
            mstore(0x00, 0x46826b5d)
8673
            mstore(0x20, p0)
8674
            mstore(0x40, p1)
8675
            mstore(0x60, 0x80)
8676
            mstore(0x80, p3)
8677
            writeString(0xa0, p2)
8678
        }
8679
        _sendLogPayload(0x1c, 0xc4);
8680
        /// @solidity memory-safe-assembly
8681
        assembly {
8682
            mstore(0x00, m0)
8683
            mstore(0x20, m1)
8684
            mstore(0x40, m2)
8685
            mstore(0x60, m3)
8686
            mstore(0x80, m4)
8687
            mstore(0xa0, m5)
8688
            mstore(0xc0, m6)
8689
        }
8690
    }
8691

                            
                        
8692
    function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
8693
        bytes32 m0;
8694
        bytes32 m1;
8695
        bytes32 m2;
8696
        bytes32 m3;
8697
        bytes32 m4;
8698
        bytes32 m5;
8699
        bytes32 m6;
8700
        bytes32 m7;
8701
        bytes32 m8;
8702
        /// @solidity memory-safe-assembly
8703
        assembly {
8704
            function writeString(pos, w) {
8705
                let length := 0
8706
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8707
                mstore(pos, length)
8708
                let shift := sub(256, shl(3, length))
8709
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8710
            }
8711
            m0 := mload(0x00)
8712
            m1 := mload(0x20)
8713
            m2 := mload(0x40)
8714
            m3 := mload(0x60)
8715
            m4 := mload(0x80)
8716
            m5 := mload(0xa0)
8717
            m6 := mload(0xc0)
8718
            m7 := mload(0xe0)
8719
            m8 := mload(0x100)
8720
            // Selector of `log(uint256,address,string,string)`.
8721
            mstore(0x00, 0x3e128ca3)
8722
            mstore(0x20, p0)
8723
            mstore(0x40, p1)
8724
            mstore(0x60, 0x80)
8725
            mstore(0x80, 0xc0)
8726
            writeString(0xa0, p2)
8727
            writeString(0xe0, p3)
8728
        }
8729
        _sendLogPayload(0x1c, 0x104);
8730
        /// @solidity memory-safe-assembly
8731
        assembly {
8732
            mstore(0x00, m0)
8733
            mstore(0x20, m1)
8734
            mstore(0x40, m2)
8735
            mstore(0x60, m3)
8736
            mstore(0x80, m4)
8737
            mstore(0xa0, m5)
8738
            mstore(0xc0, m6)
8739
            mstore(0xe0, m7)
8740
            mstore(0x100, m8)
8741
        }
8742
    }
8743

                            
                        
8744
    function log(uint256 p0, bool p1, address p2, address p3) internal pure {
8745
        bytes32 m0;
8746
        bytes32 m1;
8747
        bytes32 m2;
8748
        bytes32 m3;
8749
        bytes32 m4;
8750
        /// @solidity memory-safe-assembly
8751
        assembly {
8752
            m0 := mload(0x00)
8753
            m1 := mload(0x20)
8754
            m2 := mload(0x40)
8755
            m3 := mload(0x60)
8756
            m4 := mload(0x80)
8757
            // Selector of `log(uint256,bool,address,address)`.
8758
            mstore(0x00, 0xa1ef4cbb)
8759
            mstore(0x20, p0)
8760
            mstore(0x40, p1)
8761
            mstore(0x60, p2)
8762
            mstore(0x80, p3)
8763
        }
8764
        _sendLogPayload(0x1c, 0x84);
8765
        /// @solidity memory-safe-assembly
8766
        assembly {
8767
            mstore(0x00, m0)
8768
            mstore(0x20, m1)
8769
            mstore(0x40, m2)
8770
            mstore(0x60, m3)
8771
            mstore(0x80, m4)
8772
        }
8773
    }
8774

                            
                        
8775
    function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
8776
        bytes32 m0;
8777
        bytes32 m1;
8778
        bytes32 m2;
8779
        bytes32 m3;
8780
        bytes32 m4;
8781
        /// @solidity memory-safe-assembly
8782
        assembly {
8783
            m0 := mload(0x00)
8784
            m1 := mload(0x20)
8785
            m2 := mload(0x40)
8786
            m3 := mload(0x60)
8787
            m4 := mload(0x80)
8788
            // Selector of `log(uint256,bool,address,bool)`.
8789
            mstore(0x00, 0x454d54a5)
8790
            mstore(0x20, p0)
8791
            mstore(0x40, p1)
8792
            mstore(0x60, p2)
8793
            mstore(0x80, p3)
8794
        }
8795
        _sendLogPayload(0x1c, 0x84);
8796
        /// @solidity memory-safe-assembly
8797
        assembly {
8798
            mstore(0x00, m0)
8799
            mstore(0x20, m1)
8800
            mstore(0x40, m2)
8801
            mstore(0x60, m3)
8802
            mstore(0x80, m4)
8803
        }
8804
    }
8805

                            
                        
8806
    function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
8807
        bytes32 m0;
8808
        bytes32 m1;
8809
        bytes32 m2;
8810
        bytes32 m3;
8811
        bytes32 m4;
8812
        /// @solidity memory-safe-assembly
8813
        assembly {
8814
            m0 := mload(0x00)
8815
            m1 := mload(0x20)
8816
            m2 := mload(0x40)
8817
            m3 := mload(0x60)
8818
            m4 := mload(0x80)
8819
            // Selector of `log(uint256,bool,address,uint256)`.
8820
            mstore(0x00, 0x078287f5)
8821
            mstore(0x20, p0)
8822
            mstore(0x40, p1)
8823
            mstore(0x60, p2)
8824
            mstore(0x80, p3)
8825
        }
8826
        _sendLogPayload(0x1c, 0x84);
8827
        /// @solidity memory-safe-assembly
8828
        assembly {
8829
            mstore(0x00, m0)
8830
            mstore(0x20, m1)
8831
            mstore(0x40, m2)
8832
            mstore(0x60, m3)
8833
            mstore(0x80, m4)
8834
        }
8835
    }
8836

                            
                        
8837
    function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure {
8838
        bytes32 m0;
8839
        bytes32 m1;
8840
        bytes32 m2;
8841
        bytes32 m3;
8842
        bytes32 m4;
8843
        bytes32 m5;
8844
        bytes32 m6;
8845
        /// @solidity memory-safe-assembly
8846
        assembly {
8847
            function writeString(pos, w) {
8848
                let length := 0
8849
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8850
                mstore(pos, length)
8851
                let shift := sub(256, shl(3, length))
8852
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8853
            }
8854
            m0 := mload(0x00)
8855
            m1 := mload(0x20)
8856
            m2 := mload(0x40)
8857
            m3 := mload(0x60)
8858
            m4 := mload(0x80)
8859
            m5 := mload(0xa0)
8860
            m6 := mload(0xc0)
8861
            // Selector of `log(uint256,bool,address,string)`.
8862
            mstore(0x00, 0xade052c7)
8863
            mstore(0x20, p0)
8864
            mstore(0x40, p1)
8865
            mstore(0x60, p2)
8866
            mstore(0x80, 0x80)
8867
            writeString(0xa0, p3)
8868
        }
8869
        _sendLogPayload(0x1c, 0xc4);
8870
        /// @solidity memory-safe-assembly
8871
        assembly {
8872
            mstore(0x00, m0)
8873
            mstore(0x20, m1)
8874
            mstore(0x40, m2)
8875
            mstore(0x60, m3)
8876
            mstore(0x80, m4)
8877
            mstore(0xa0, m5)
8878
            mstore(0xc0, m6)
8879
        }
8880
    }
8881

                            
                        
8882
    function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
8883
        bytes32 m0;
8884
        bytes32 m1;
8885
        bytes32 m2;
8886
        bytes32 m3;
8887
        bytes32 m4;
8888
        /// @solidity memory-safe-assembly
8889
        assembly {
8890
            m0 := mload(0x00)
8891
            m1 := mload(0x20)
8892
            m2 := mload(0x40)
8893
            m3 := mload(0x60)
8894
            m4 := mload(0x80)
8895
            // Selector of `log(uint256,bool,bool,address)`.
8896
            mstore(0x00, 0x69640b59)
8897
            mstore(0x20, p0)
8898
            mstore(0x40, p1)
8899
            mstore(0x60, p2)
8900
            mstore(0x80, p3)
8901
        }
8902
        _sendLogPayload(0x1c, 0x84);
8903
        /// @solidity memory-safe-assembly
8904
        assembly {
8905
            mstore(0x00, m0)
8906
            mstore(0x20, m1)
8907
            mstore(0x40, m2)
8908
            mstore(0x60, m3)
8909
            mstore(0x80, m4)
8910
        }
8911
    }
8912

                            
                        
8913
    function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
8914
        bytes32 m0;
8915
        bytes32 m1;
8916
        bytes32 m2;
8917
        bytes32 m3;
8918
        bytes32 m4;
8919
        /// @solidity memory-safe-assembly
8920
        assembly {
8921
            m0 := mload(0x00)
8922
            m1 := mload(0x20)
8923
            m2 := mload(0x40)
8924
            m3 := mload(0x60)
8925
            m4 := mload(0x80)
8926
            // Selector of `log(uint256,bool,bool,bool)`.
8927
            mstore(0x00, 0xb6f577a1)
8928
            mstore(0x20, p0)
8929
            mstore(0x40, p1)
8930
            mstore(0x60, p2)
8931
            mstore(0x80, p3)
8932
        }
8933
        _sendLogPayload(0x1c, 0x84);
8934
        /// @solidity memory-safe-assembly
8935
        assembly {
8936
            mstore(0x00, m0)
8937
            mstore(0x20, m1)
8938
            mstore(0x40, m2)
8939
            mstore(0x60, m3)
8940
            mstore(0x80, m4)
8941
        }
8942
    }
8943

                            
                        
8944
    function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
8945
        bytes32 m0;
8946
        bytes32 m1;
8947
        bytes32 m2;
8948
        bytes32 m3;
8949
        bytes32 m4;
8950
        /// @solidity memory-safe-assembly
8951
        assembly {
8952
            m0 := mload(0x00)
8953
            m1 := mload(0x20)
8954
            m2 := mload(0x40)
8955
            m3 := mload(0x60)
8956
            m4 := mload(0x80)
8957
            // Selector of `log(uint256,bool,bool,uint256)`.
8958
            mstore(0x00, 0x7464ce23)
8959
            mstore(0x20, p0)
8960
            mstore(0x40, p1)
8961
            mstore(0x60, p2)
8962
            mstore(0x80, p3)
8963
        }
8964
        _sendLogPayload(0x1c, 0x84);
8965
        /// @solidity memory-safe-assembly
8966
        assembly {
8967
            mstore(0x00, m0)
8968
            mstore(0x20, m1)
8969
            mstore(0x40, m2)
8970
            mstore(0x60, m3)
8971
            mstore(0x80, m4)
8972
        }
8973
    }
8974

                            
                        
8975
    function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure {
8976
        bytes32 m0;
8977
        bytes32 m1;
8978
        bytes32 m2;
8979
        bytes32 m3;
8980
        bytes32 m4;
8981
        bytes32 m5;
8982
        bytes32 m6;
8983
        /// @solidity memory-safe-assembly
8984
        assembly {
8985
            function writeString(pos, w) {
8986
                let length := 0
8987
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
8988
                mstore(pos, length)
8989
                let shift := sub(256, shl(3, length))
8990
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
8991
            }
8992
            m0 := mload(0x00)
8993
            m1 := mload(0x20)
8994
            m2 := mload(0x40)
8995
            m3 := mload(0x60)
8996
            m4 := mload(0x80)
8997
            m5 := mload(0xa0)
8998
            m6 := mload(0xc0)
8999
            // Selector of `log(uint256,bool,bool,string)`.
9000
            mstore(0x00, 0xdddb9561)
9001
            mstore(0x20, p0)
9002
            mstore(0x40, p1)
9003
            mstore(0x60, p2)
9004
            mstore(0x80, 0x80)
9005
            writeString(0xa0, p3)
9006
        }
9007
        _sendLogPayload(0x1c, 0xc4);
9008
        /// @solidity memory-safe-assembly
9009
        assembly {
9010
            mstore(0x00, m0)
9011
            mstore(0x20, m1)
9012
            mstore(0x40, m2)
9013
            mstore(0x60, m3)
9014
            mstore(0x80, m4)
9015
            mstore(0xa0, m5)
9016
            mstore(0xc0, m6)
9017
        }
9018
    }
9019

                            
                        
9020
    function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
9021
        bytes32 m0;
9022
        bytes32 m1;
9023
        bytes32 m2;
9024
        bytes32 m3;
9025
        bytes32 m4;
9026
        /// @solidity memory-safe-assembly
9027
        assembly {
9028
            m0 := mload(0x00)
9029
            m1 := mload(0x20)
9030
            m2 := mload(0x40)
9031
            m3 := mload(0x60)
9032
            m4 := mload(0x80)
9033
            // Selector of `log(uint256,bool,uint256,address)`.
9034
            mstore(0x00, 0x88cb6041)
9035
            mstore(0x20, p0)
9036
            mstore(0x40, p1)
9037
            mstore(0x60, p2)
9038
            mstore(0x80, p3)
9039
        }
9040
        _sendLogPayload(0x1c, 0x84);
9041
        /// @solidity memory-safe-assembly
9042
        assembly {
9043
            mstore(0x00, m0)
9044
            mstore(0x20, m1)
9045
            mstore(0x40, m2)
9046
            mstore(0x60, m3)
9047
            mstore(0x80, m4)
9048
        }
9049
    }
9050

                            
                        
9051
    function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
9052
        bytes32 m0;
9053
        bytes32 m1;
9054
        bytes32 m2;
9055
        bytes32 m3;
9056
        bytes32 m4;
9057
        /// @solidity memory-safe-assembly
9058
        assembly {
9059
            m0 := mload(0x00)
9060
            m1 := mload(0x20)
9061
            m2 := mload(0x40)
9062
            m3 := mload(0x60)
9063
            m4 := mload(0x80)
9064
            // Selector of `log(uint256,bool,uint256,bool)`.
9065
            mstore(0x00, 0x91a02e2a)
9066
            mstore(0x20, p0)
9067
            mstore(0x40, p1)
9068
            mstore(0x60, p2)
9069
            mstore(0x80, p3)
9070
        }
9071
        _sendLogPayload(0x1c, 0x84);
9072
        /// @solidity memory-safe-assembly
9073
        assembly {
9074
            mstore(0x00, m0)
9075
            mstore(0x20, m1)
9076
            mstore(0x40, m2)
9077
            mstore(0x60, m3)
9078
            mstore(0x80, m4)
9079
        }
9080
    }
9081

                            
                        
9082
    function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
9083
        bytes32 m0;
9084
        bytes32 m1;
9085
        bytes32 m2;
9086
        bytes32 m3;
9087
        bytes32 m4;
9088
        /// @solidity memory-safe-assembly
9089
        assembly {
9090
            m0 := mload(0x00)
9091
            m1 := mload(0x20)
9092
            m2 := mload(0x40)
9093
            m3 := mload(0x60)
9094
            m4 := mload(0x80)
9095
            // Selector of `log(uint256,bool,uint256,uint256)`.
9096
            mstore(0x00, 0xc6acc7a8)
9097
            mstore(0x20, p0)
9098
            mstore(0x40, p1)
9099
            mstore(0x60, p2)
9100
            mstore(0x80, p3)
9101
        }
9102
        _sendLogPayload(0x1c, 0x84);
9103
        /// @solidity memory-safe-assembly
9104
        assembly {
9105
            mstore(0x00, m0)
9106
            mstore(0x20, m1)
9107
            mstore(0x40, m2)
9108
            mstore(0x60, m3)
9109
            mstore(0x80, m4)
9110
        }
9111
    }
9112

                            
                        
9113
    function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
9114
        bytes32 m0;
9115
        bytes32 m1;
9116
        bytes32 m2;
9117
        bytes32 m3;
9118
        bytes32 m4;
9119
        bytes32 m5;
9120
        bytes32 m6;
9121
        /// @solidity memory-safe-assembly
9122
        assembly {
9123
            function writeString(pos, w) {
9124
                let length := 0
9125
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9126
                mstore(pos, length)
9127
                let shift := sub(256, shl(3, length))
9128
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9129
            }
9130
            m0 := mload(0x00)
9131
            m1 := mload(0x20)
9132
            m2 := mload(0x40)
9133
            m3 := mload(0x60)
9134
            m4 := mload(0x80)
9135
            m5 := mload(0xa0)
9136
            m6 := mload(0xc0)
9137
            // Selector of `log(uint256,bool,uint256,string)`.
9138
            mstore(0x00, 0xde03e774)
9139
            mstore(0x20, p0)
9140
            mstore(0x40, p1)
9141
            mstore(0x60, p2)
9142
            mstore(0x80, 0x80)
9143
            writeString(0xa0, p3)
9144
        }
9145
        _sendLogPayload(0x1c, 0xc4);
9146
        /// @solidity memory-safe-assembly
9147
        assembly {
9148
            mstore(0x00, m0)
9149
            mstore(0x20, m1)
9150
            mstore(0x40, m2)
9151
            mstore(0x60, m3)
9152
            mstore(0x80, m4)
9153
            mstore(0xa0, m5)
9154
            mstore(0xc0, m6)
9155
        }
9156
    }
9157

                            
                        
9158
    function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure {
9159
        bytes32 m0;
9160
        bytes32 m1;
9161
        bytes32 m2;
9162
        bytes32 m3;
9163
        bytes32 m4;
9164
        bytes32 m5;
9165
        bytes32 m6;
9166
        /// @solidity memory-safe-assembly
9167
        assembly {
9168
            function writeString(pos, w) {
9169
                let length := 0
9170
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9171
                mstore(pos, length)
9172
                let shift := sub(256, shl(3, length))
9173
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9174
            }
9175
            m0 := mload(0x00)
9176
            m1 := mload(0x20)
9177
            m2 := mload(0x40)
9178
            m3 := mload(0x60)
9179
            m4 := mload(0x80)
9180
            m5 := mload(0xa0)
9181
            m6 := mload(0xc0)
9182
            // Selector of `log(uint256,bool,string,address)`.
9183
            mstore(0x00, 0xef529018)
9184
            mstore(0x20, p0)
9185
            mstore(0x40, p1)
9186
            mstore(0x60, 0x80)
9187
            mstore(0x80, p3)
9188
            writeString(0xa0, p2)
9189
        }
9190
        _sendLogPayload(0x1c, 0xc4);
9191
        /// @solidity memory-safe-assembly
9192
        assembly {
9193
            mstore(0x00, m0)
9194
            mstore(0x20, m1)
9195
            mstore(0x40, m2)
9196
            mstore(0x60, m3)
9197
            mstore(0x80, m4)
9198
            mstore(0xa0, m5)
9199
            mstore(0xc0, m6)
9200
        }
9201
    }
9202

                            
                        
9203
    function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure {
9204
        bytes32 m0;
9205
        bytes32 m1;
9206
        bytes32 m2;
9207
        bytes32 m3;
9208
        bytes32 m4;
9209
        bytes32 m5;
9210
        bytes32 m6;
9211
        /// @solidity memory-safe-assembly
9212
        assembly {
9213
            function writeString(pos, w) {
9214
                let length := 0
9215
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9216
                mstore(pos, length)
9217
                let shift := sub(256, shl(3, length))
9218
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9219
            }
9220
            m0 := mload(0x00)
9221
            m1 := mload(0x20)
9222
            m2 := mload(0x40)
9223
            m3 := mload(0x60)
9224
            m4 := mload(0x80)
9225
            m5 := mload(0xa0)
9226
            m6 := mload(0xc0)
9227
            // Selector of `log(uint256,bool,string,bool)`.
9228
            mstore(0x00, 0xeb928d7f)
9229
            mstore(0x20, p0)
9230
            mstore(0x40, p1)
9231
            mstore(0x60, 0x80)
9232
            mstore(0x80, p3)
9233
            writeString(0xa0, p2)
9234
        }
9235
        _sendLogPayload(0x1c, 0xc4);
9236
        /// @solidity memory-safe-assembly
9237
        assembly {
9238
            mstore(0x00, m0)
9239
            mstore(0x20, m1)
9240
            mstore(0x40, m2)
9241
            mstore(0x60, m3)
9242
            mstore(0x80, m4)
9243
            mstore(0xa0, m5)
9244
            mstore(0xc0, m6)
9245
        }
9246
    }
9247

                            
                        
9248
    function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
9249
        bytes32 m0;
9250
        bytes32 m1;
9251
        bytes32 m2;
9252
        bytes32 m3;
9253
        bytes32 m4;
9254
        bytes32 m5;
9255
        bytes32 m6;
9256
        /// @solidity memory-safe-assembly
9257
        assembly {
9258
            function writeString(pos, w) {
9259
                let length := 0
9260
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9261
                mstore(pos, length)
9262
                let shift := sub(256, shl(3, length))
9263
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9264
            }
9265
            m0 := mload(0x00)
9266
            m1 := mload(0x20)
9267
            m2 := mload(0x40)
9268
            m3 := mload(0x60)
9269
            m4 := mload(0x80)
9270
            m5 := mload(0xa0)
9271
            m6 := mload(0xc0)
9272
            // Selector of `log(uint256,bool,string,uint256)`.
9273
            mstore(0x00, 0x2c1d0746)
9274
            mstore(0x20, p0)
9275
            mstore(0x40, p1)
9276
            mstore(0x60, 0x80)
9277
            mstore(0x80, p3)
9278
            writeString(0xa0, p2)
9279
        }
9280
        _sendLogPayload(0x1c, 0xc4);
9281
        /// @solidity memory-safe-assembly
9282
        assembly {
9283
            mstore(0x00, m0)
9284
            mstore(0x20, m1)
9285
            mstore(0x40, m2)
9286
            mstore(0x60, m3)
9287
            mstore(0x80, m4)
9288
            mstore(0xa0, m5)
9289
            mstore(0xc0, m6)
9290
        }
9291
    }
9292

                            
                        
9293
    function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
9294
        bytes32 m0;
9295
        bytes32 m1;
9296
        bytes32 m2;
9297
        bytes32 m3;
9298
        bytes32 m4;
9299
        bytes32 m5;
9300
        bytes32 m6;
9301
        bytes32 m7;
9302
        bytes32 m8;
9303
        /// @solidity memory-safe-assembly
9304
        assembly {
9305
            function writeString(pos, w) {
9306
                let length := 0
9307
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9308
                mstore(pos, length)
9309
                let shift := sub(256, shl(3, length))
9310
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9311
            }
9312
            m0 := mload(0x00)
9313
            m1 := mload(0x20)
9314
            m2 := mload(0x40)
9315
            m3 := mload(0x60)
9316
            m4 := mload(0x80)
9317
            m5 := mload(0xa0)
9318
            m6 := mload(0xc0)
9319
            m7 := mload(0xe0)
9320
            m8 := mload(0x100)
9321
            // Selector of `log(uint256,bool,string,string)`.
9322
            mstore(0x00, 0x68c8b8bd)
9323
            mstore(0x20, p0)
9324
            mstore(0x40, p1)
9325
            mstore(0x60, 0x80)
9326
            mstore(0x80, 0xc0)
9327
            writeString(0xa0, p2)
9328
            writeString(0xe0, p3)
9329
        }
9330
        _sendLogPayload(0x1c, 0x104);
9331
        /// @solidity memory-safe-assembly
9332
        assembly {
9333
            mstore(0x00, m0)
9334
            mstore(0x20, m1)
9335
            mstore(0x40, m2)
9336
            mstore(0x60, m3)
9337
            mstore(0x80, m4)
9338
            mstore(0xa0, m5)
9339
            mstore(0xc0, m6)
9340
            mstore(0xe0, m7)
9341
            mstore(0x100, m8)
9342
        }
9343
    }
9344

                            
                        
9345
    function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
9346
        bytes32 m0;
9347
        bytes32 m1;
9348
        bytes32 m2;
9349
        bytes32 m3;
9350
        bytes32 m4;
9351
        /// @solidity memory-safe-assembly
9352
        assembly {
9353
            m0 := mload(0x00)
9354
            m1 := mload(0x20)
9355
            m2 := mload(0x40)
9356
            m3 := mload(0x60)
9357
            m4 := mload(0x80)
9358
            // Selector of `log(uint256,uint256,address,address)`.
9359
            mstore(0x00, 0x56a5d1b1)
9360
            mstore(0x20, p0)
9361
            mstore(0x40, p1)
9362
            mstore(0x60, p2)
9363
            mstore(0x80, p3)
9364
        }
9365
        _sendLogPayload(0x1c, 0x84);
9366
        /// @solidity memory-safe-assembly
9367
        assembly {
9368
            mstore(0x00, m0)
9369
            mstore(0x20, m1)
9370
            mstore(0x40, m2)
9371
            mstore(0x60, m3)
9372
            mstore(0x80, m4)
9373
        }
9374
    }
9375

                            
                        
9376
    function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
9377
        bytes32 m0;
9378
        bytes32 m1;
9379
        bytes32 m2;
9380
        bytes32 m3;
9381
        bytes32 m4;
9382
        /// @solidity memory-safe-assembly
9383
        assembly {
9384
            m0 := mload(0x00)
9385
            m1 := mload(0x20)
9386
            m2 := mload(0x40)
9387
            m3 := mload(0x60)
9388
            m4 := mload(0x80)
9389
            // Selector of `log(uint256,uint256,address,bool)`.
9390
            mstore(0x00, 0x15cac476)
9391
            mstore(0x20, p0)
9392
            mstore(0x40, p1)
9393
            mstore(0x60, p2)
9394
            mstore(0x80, p3)
9395
        }
9396
        _sendLogPayload(0x1c, 0x84);
9397
        /// @solidity memory-safe-assembly
9398
        assembly {
9399
            mstore(0x00, m0)
9400
            mstore(0x20, m1)
9401
            mstore(0x40, m2)
9402
            mstore(0x60, m3)
9403
            mstore(0x80, m4)
9404
        }
9405
    }
9406

                            
                        
9407
    function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
9408
        bytes32 m0;
9409
        bytes32 m1;
9410
        bytes32 m2;
9411
        bytes32 m3;
9412
        bytes32 m4;
9413
        /// @solidity memory-safe-assembly
9414
        assembly {
9415
            m0 := mload(0x00)
9416
            m1 := mload(0x20)
9417
            m2 := mload(0x40)
9418
            m3 := mload(0x60)
9419
            m4 := mload(0x80)
9420
            // Selector of `log(uint256,uint256,address,uint256)`.
9421
            mstore(0x00, 0x88f6e4b2)
9422
            mstore(0x20, p0)
9423
            mstore(0x40, p1)
9424
            mstore(0x60, p2)
9425
            mstore(0x80, p3)
9426
        }
9427
        _sendLogPayload(0x1c, 0x84);
9428
        /// @solidity memory-safe-assembly
9429
        assembly {
9430
            mstore(0x00, m0)
9431
            mstore(0x20, m1)
9432
            mstore(0x40, m2)
9433
            mstore(0x60, m3)
9434
            mstore(0x80, m4)
9435
        }
9436
    }
9437

                            
                        
9438
    function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure {
9439
        bytes32 m0;
9440
        bytes32 m1;
9441
        bytes32 m2;
9442
        bytes32 m3;
9443
        bytes32 m4;
9444
        bytes32 m5;
9445
        bytes32 m6;
9446
        /// @solidity memory-safe-assembly
9447
        assembly {
9448
            function writeString(pos, w) {
9449
                let length := 0
9450
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9451
                mstore(pos, length)
9452
                let shift := sub(256, shl(3, length))
9453
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9454
            }
9455
            m0 := mload(0x00)
9456
            m1 := mload(0x20)
9457
            m2 := mload(0x40)
9458
            m3 := mload(0x60)
9459
            m4 := mload(0x80)
9460
            m5 := mload(0xa0)
9461
            m6 := mload(0xc0)
9462
            // Selector of `log(uint256,uint256,address,string)`.
9463
            mstore(0x00, 0x6cde40b8)
9464
            mstore(0x20, p0)
9465
            mstore(0x40, p1)
9466
            mstore(0x60, p2)
9467
            mstore(0x80, 0x80)
9468
            writeString(0xa0, p3)
9469
        }
9470
        _sendLogPayload(0x1c, 0xc4);
9471
        /// @solidity memory-safe-assembly
9472
        assembly {
9473
            mstore(0x00, m0)
9474
            mstore(0x20, m1)
9475
            mstore(0x40, m2)
9476
            mstore(0x60, m3)
9477
            mstore(0x80, m4)
9478
            mstore(0xa0, m5)
9479
            mstore(0xc0, m6)
9480
        }
9481
    }
9482

                            
                        
9483
    function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
9484
        bytes32 m0;
9485
        bytes32 m1;
9486
        bytes32 m2;
9487
        bytes32 m3;
9488
        bytes32 m4;
9489
        /// @solidity memory-safe-assembly
9490
        assembly {
9491
            m0 := mload(0x00)
9492
            m1 := mload(0x20)
9493
            m2 := mload(0x40)
9494
            m3 := mload(0x60)
9495
            m4 := mload(0x80)
9496
            // Selector of `log(uint256,uint256,bool,address)`.
9497
            mstore(0x00, 0x9a816a83)
9498
            mstore(0x20, p0)
9499
            mstore(0x40, p1)
9500
            mstore(0x60, p2)
9501
            mstore(0x80, p3)
9502
        }
9503
        _sendLogPayload(0x1c, 0x84);
9504
        /// @solidity memory-safe-assembly
9505
        assembly {
9506
            mstore(0x00, m0)
9507
            mstore(0x20, m1)
9508
            mstore(0x40, m2)
9509
            mstore(0x60, m3)
9510
            mstore(0x80, m4)
9511
        }
9512
    }
9513

                            
                        
9514
    function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
9515
        bytes32 m0;
9516
        bytes32 m1;
9517
        bytes32 m2;
9518
        bytes32 m3;
9519
        bytes32 m4;
9520
        /// @solidity memory-safe-assembly
9521
        assembly {
9522
            m0 := mload(0x00)
9523
            m1 := mload(0x20)
9524
            m2 := mload(0x40)
9525
            m3 := mload(0x60)
9526
            m4 := mload(0x80)
9527
            // Selector of `log(uint256,uint256,bool,bool)`.
9528
            mstore(0x00, 0xab085ae6)
9529
            mstore(0x20, p0)
9530
            mstore(0x40, p1)
9531
            mstore(0x60, p2)
9532
            mstore(0x80, p3)
9533
        }
9534
        _sendLogPayload(0x1c, 0x84);
9535
        /// @solidity memory-safe-assembly
9536
        assembly {
9537
            mstore(0x00, m0)
9538
            mstore(0x20, m1)
9539
            mstore(0x40, m2)
9540
            mstore(0x60, m3)
9541
            mstore(0x80, m4)
9542
        }
9543
    }
9544

                            
                        
9545
    function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
9546
        bytes32 m0;
9547
        bytes32 m1;
9548
        bytes32 m2;
9549
        bytes32 m3;
9550
        bytes32 m4;
9551
        /// @solidity memory-safe-assembly
9552
        assembly {
9553
            m0 := mload(0x00)
9554
            m1 := mload(0x20)
9555
            m2 := mload(0x40)
9556
            m3 := mload(0x60)
9557
            m4 := mload(0x80)
9558
            // Selector of `log(uint256,uint256,bool,uint256)`.
9559
            mstore(0x00, 0xeb7f6fd2)
9560
            mstore(0x20, p0)
9561
            mstore(0x40, p1)
9562
            mstore(0x60, p2)
9563
            mstore(0x80, p3)
9564
        }
9565
        _sendLogPayload(0x1c, 0x84);
9566
        /// @solidity memory-safe-assembly
9567
        assembly {
9568
            mstore(0x00, m0)
9569
            mstore(0x20, m1)
9570
            mstore(0x40, m2)
9571
            mstore(0x60, m3)
9572
            mstore(0x80, m4)
9573
        }
9574
    }
9575

                            
                        
9576
    function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
9577
        bytes32 m0;
9578
        bytes32 m1;
9579
        bytes32 m2;
9580
        bytes32 m3;
9581
        bytes32 m4;
9582
        bytes32 m5;
9583
        bytes32 m6;
9584
        /// @solidity memory-safe-assembly
9585
        assembly {
9586
            function writeString(pos, w) {
9587
                let length := 0
9588
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9589
                mstore(pos, length)
9590
                let shift := sub(256, shl(3, length))
9591
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9592
            }
9593
            m0 := mload(0x00)
9594
            m1 := mload(0x20)
9595
            m2 := mload(0x40)
9596
            m3 := mload(0x60)
9597
            m4 := mload(0x80)
9598
            m5 := mload(0xa0)
9599
            m6 := mload(0xc0)
9600
            // Selector of `log(uint256,uint256,bool,string)`.
9601
            mstore(0x00, 0xa5b4fc99)
9602
            mstore(0x20, p0)
9603
            mstore(0x40, p1)
9604
            mstore(0x60, p2)
9605
            mstore(0x80, 0x80)
9606
            writeString(0xa0, p3)
9607
        }
9608
        _sendLogPayload(0x1c, 0xc4);
9609
        /// @solidity memory-safe-assembly
9610
        assembly {
9611
            mstore(0x00, m0)
9612
            mstore(0x20, m1)
9613
            mstore(0x40, m2)
9614
            mstore(0x60, m3)
9615
            mstore(0x80, m4)
9616
            mstore(0xa0, m5)
9617
            mstore(0xc0, m6)
9618
        }
9619
    }
9620

                            
                        
9621
    function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
9622
        bytes32 m0;
9623
        bytes32 m1;
9624
        bytes32 m2;
9625
        bytes32 m3;
9626
        bytes32 m4;
9627
        /// @solidity memory-safe-assembly
9628
        assembly {
9629
            m0 := mload(0x00)
9630
            m1 := mload(0x20)
9631
            m2 := mload(0x40)
9632
            m3 := mload(0x60)
9633
            m4 := mload(0x80)
9634
            // Selector of `log(uint256,uint256,uint256,address)`.
9635
            mstore(0x00, 0xfa8185af)
9636
            mstore(0x20, p0)
9637
            mstore(0x40, p1)
9638
            mstore(0x60, p2)
9639
            mstore(0x80, p3)
9640
        }
9641
        _sendLogPayload(0x1c, 0x84);
9642
        /// @solidity memory-safe-assembly
9643
        assembly {
9644
            mstore(0x00, m0)
9645
            mstore(0x20, m1)
9646
            mstore(0x40, m2)
9647
            mstore(0x60, m3)
9648
            mstore(0x80, m4)
9649
        }
9650
    }
9651

                            
                        
9652
    function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
9653
        bytes32 m0;
9654
        bytes32 m1;
9655
        bytes32 m2;
9656
        bytes32 m3;
9657
        bytes32 m4;
9658
        /// @solidity memory-safe-assembly
9659
        assembly {
9660
            m0 := mload(0x00)
9661
            m1 := mload(0x20)
9662
            m2 := mload(0x40)
9663
            m3 := mload(0x60)
9664
            m4 := mload(0x80)
9665
            // Selector of `log(uint256,uint256,uint256,bool)`.
9666
            mstore(0x00, 0xc598d185)
9667
            mstore(0x20, p0)
9668
            mstore(0x40, p1)
9669
            mstore(0x60, p2)
9670
            mstore(0x80, p3)
9671
        }
9672
        _sendLogPayload(0x1c, 0x84);
9673
        /// @solidity memory-safe-assembly
9674
        assembly {
9675
            mstore(0x00, m0)
9676
            mstore(0x20, m1)
9677
            mstore(0x40, m2)
9678
            mstore(0x60, m3)
9679
            mstore(0x80, m4)
9680
        }
9681
    }
9682

                            
                        
9683
    function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
9684
        bytes32 m0;
9685
        bytes32 m1;
9686
        bytes32 m2;
9687
        bytes32 m3;
9688
        bytes32 m4;
9689
        /// @solidity memory-safe-assembly
9690
        assembly {
9691
            m0 := mload(0x00)
9692
            m1 := mload(0x20)
9693
            m2 := mload(0x40)
9694
            m3 := mload(0x60)
9695
            m4 := mload(0x80)
9696
            // Selector of `log(uint256,uint256,uint256,uint256)`.
9697
            mstore(0x00, 0x193fb800)
9698
            mstore(0x20, p0)
9699
            mstore(0x40, p1)
9700
            mstore(0x60, p2)
9701
            mstore(0x80, p3)
9702
        }
9703
        _sendLogPayload(0x1c, 0x84);
9704
        /// @solidity memory-safe-assembly
9705
        assembly {
9706
            mstore(0x00, m0)
9707
            mstore(0x20, m1)
9708
            mstore(0x40, m2)
9709
            mstore(0x60, m3)
9710
            mstore(0x80, m4)
9711
        }
9712
    }
9713

                            
                        
9714
    function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
9715
        bytes32 m0;
9716
        bytes32 m1;
9717
        bytes32 m2;
9718
        bytes32 m3;
9719
        bytes32 m4;
9720
        bytes32 m5;
9721
        bytes32 m6;
9722
        /// @solidity memory-safe-assembly
9723
        assembly {
9724
            function writeString(pos, w) {
9725
                let length := 0
9726
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9727
                mstore(pos, length)
9728
                let shift := sub(256, shl(3, length))
9729
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9730
            }
9731
            m0 := mload(0x00)
9732
            m1 := mload(0x20)
9733
            m2 := mload(0x40)
9734
            m3 := mload(0x60)
9735
            m4 := mload(0x80)
9736
            m5 := mload(0xa0)
9737
            m6 := mload(0xc0)
9738
            // Selector of `log(uint256,uint256,uint256,string)`.
9739
            mstore(0x00, 0x59cfcbe3)
9740
            mstore(0x20, p0)
9741
            mstore(0x40, p1)
9742
            mstore(0x60, p2)
9743
            mstore(0x80, 0x80)
9744
            writeString(0xa0, p3)
9745
        }
9746
        _sendLogPayload(0x1c, 0xc4);
9747
        /// @solidity memory-safe-assembly
9748
        assembly {
9749
            mstore(0x00, m0)
9750
            mstore(0x20, m1)
9751
            mstore(0x40, m2)
9752
            mstore(0x60, m3)
9753
            mstore(0x80, m4)
9754
            mstore(0xa0, m5)
9755
            mstore(0xc0, m6)
9756
        }
9757
    }
9758

                            
                        
9759
    function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure {
9760
        bytes32 m0;
9761
        bytes32 m1;
9762
        bytes32 m2;
9763
        bytes32 m3;
9764
        bytes32 m4;
9765
        bytes32 m5;
9766
        bytes32 m6;
9767
        /// @solidity memory-safe-assembly
9768
        assembly {
9769
            function writeString(pos, w) {
9770
                let length := 0
9771
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9772
                mstore(pos, length)
9773
                let shift := sub(256, shl(3, length))
9774
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9775
            }
9776
            m0 := mload(0x00)
9777
            m1 := mload(0x20)
9778
            m2 := mload(0x40)
9779
            m3 := mload(0x60)
9780
            m4 := mload(0x80)
9781
            m5 := mload(0xa0)
9782
            m6 := mload(0xc0)
9783
            // Selector of `log(uint256,uint256,string,address)`.
9784
            mstore(0x00, 0x42d21db7)
9785
            mstore(0x20, p0)
9786
            mstore(0x40, p1)
9787
            mstore(0x60, 0x80)
9788
            mstore(0x80, p3)
9789
            writeString(0xa0, p2)
9790
        }
9791
        _sendLogPayload(0x1c, 0xc4);
9792
        /// @solidity memory-safe-assembly
9793
        assembly {
9794
            mstore(0x00, m0)
9795
            mstore(0x20, m1)
9796
            mstore(0x40, m2)
9797
            mstore(0x60, m3)
9798
            mstore(0x80, m4)
9799
            mstore(0xa0, m5)
9800
            mstore(0xc0, m6)
9801
        }
9802
    }
9803

                            
                        
9804
    function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
9805
        bytes32 m0;
9806
        bytes32 m1;
9807
        bytes32 m2;
9808
        bytes32 m3;
9809
        bytes32 m4;
9810
        bytes32 m5;
9811
        bytes32 m6;
9812
        /// @solidity memory-safe-assembly
9813
        assembly {
9814
            function writeString(pos, w) {
9815
                let length := 0
9816
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9817
                mstore(pos, length)
9818
                let shift := sub(256, shl(3, length))
9819
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9820
            }
9821
            m0 := mload(0x00)
9822
            m1 := mload(0x20)
9823
            m2 := mload(0x40)
9824
            m3 := mload(0x60)
9825
            m4 := mload(0x80)
9826
            m5 := mload(0xa0)
9827
            m6 := mload(0xc0)
9828
            // Selector of `log(uint256,uint256,string,bool)`.
9829
            mstore(0x00, 0x7af6ab25)
9830
            mstore(0x20, p0)
9831
            mstore(0x40, p1)
9832
            mstore(0x60, 0x80)
9833
            mstore(0x80, p3)
9834
            writeString(0xa0, p2)
9835
        }
9836
        _sendLogPayload(0x1c, 0xc4);
9837
        /// @solidity memory-safe-assembly
9838
        assembly {
9839
            mstore(0x00, m0)
9840
            mstore(0x20, m1)
9841
            mstore(0x40, m2)
9842
            mstore(0x60, m3)
9843
            mstore(0x80, m4)
9844
            mstore(0xa0, m5)
9845
            mstore(0xc0, m6)
9846
        }
9847
    }
9848

                            
                        
9849
    function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
9850
        bytes32 m0;
9851
        bytes32 m1;
9852
        bytes32 m2;
9853
        bytes32 m3;
9854
        bytes32 m4;
9855
        bytes32 m5;
9856
        bytes32 m6;
9857
        /// @solidity memory-safe-assembly
9858
        assembly {
9859
            function writeString(pos, w) {
9860
                let length := 0
9861
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9862
                mstore(pos, length)
9863
                let shift := sub(256, shl(3, length))
9864
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9865
            }
9866
            m0 := mload(0x00)
9867
            m1 := mload(0x20)
9868
            m2 := mload(0x40)
9869
            m3 := mload(0x60)
9870
            m4 := mload(0x80)
9871
            m5 := mload(0xa0)
9872
            m6 := mload(0xc0)
9873
            // Selector of `log(uint256,uint256,string,uint256)`.
9874
            mstore(0x00, 0x5da297eb)
9875
            mstore(0x20, p0)
9876
            mstore(0x40, p1)
9877
            mstore(0x60, 0x80)
9878
            mstore(0x80, p3)
9879
            writeString(0xa0, p2)
9880
        }
9881
        _sendLogPayload(0x1c, 0xc4);
9882
        /// @solidity memory-safe-assembly
9883
        assembly {
9884
            mstore(0x00, m0)
9885
            mstore(0x20, m1)
9886
            mstore(0x40, m2)
9887
            mstore(0x60, m3)
9888
            mstore(0x80, m4)
9889
            mstore(0xa0, m5)
9890
            mstore(0xc0, m6)
9891
        }
9892
    }
9893

                            
                        
9894
    function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
9895
        bytes32 m0;
9896
        bytes32 m1;
9897
        bytes32 m2;
9898
        bytes32 m3;
9899
        bytes32 m4;
9900
        bytes32 m5;
9901
        bytes32 m6;
9902
        bytes32 m7;
9903
        bytes32 m8;
9904
        /// @solidity memory-safe-assembly
9905
        assembly {
9906
            function writeString(pos, w) {
9907
                let length := 0
9908
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9909
                mstore(pos, length)
9910
                let shift := sub(256, shl(3, length))
9911
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9912
            }
9913
            m0 := mload(0x00)
9914
            m1 := mload(0x20)
9915
            m2 := mload(0x40)
9916
            m3 := mload(0x60)
9917
            m4 := mload(0x80)
9918
            m5 := mload(0xa0)
9919
            m6 := mload(0xc0)
9920
            m7 := mload(0xe0)
9921
            m8 := mload(0x100)
9922
            // Selector of `log(uint256,uint256,string,string)`.
9923
            mstore(0x00, 0x27d8afd2)
9924
            mstore(0x20, p0)
9925
            mstore(0x40, p1)
9926
            mstore(0x60, 0x80)
9927
            mstore(0x80, 0xc0)
9928
            writeString(0xa0, p2)
9929
            writeString(0xe0, p3)
9930
        }
9931
        _sendLogPayload(0x1c, 0x104);
9932
        /// @solidity memory-safe-assembly
9933
        assembly {
9934
            mstore(0x00, m0)
9935
            mstore(0x20, m1)
9936
            mstore(0x40, m2)
9937
            mstore(0x60, m3)
9938
            mstore(0x80, m4)
9939
            mstore(0xa0, m5)
9940
            mstore(0xc0, m6)
9941
            mstore(0xe0, m7)
9942
            mstore(0x100, m8)
9943
        }
9944
    }
9945

                            
                        
9946
    function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure {
9947
        bytes32 m0;
9948
        bytes32 m1;
9949
        bytes32 m2;
9950
        bytes32 m3;
9951
        bytes32 m4;
9952
        bytes32 m5;
9953
        bytes32 m6;
9954
        /// @solidity memory-safe-assembly
9955
        assembly {
9956
            function writeString(pos, w) {
9957
                let length := 0
9958
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
9959
                mstore(pos, length)
9960
                let shift := sub(256, shl(3, length))
9961
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
9962
            }
9963
            m0 := mload(0x00)
9964
            m1 := mload(0x20)
9965
            m2 := mload(0x40)
9966
            m3 := mload(0x60)
9967
            m4 := mload(0x80)
9968
            m5 := mload(0xa0)
9969
            m6 := mload(0xc0)
9970
            // Selector of `log(uint256,string,address,address)`.
9971
            mstore(0x00, 0x6168ed61)
9972
            mstore(0x20, p0)
9973
            mstore(0x40, 0x80)
9974
            mstore(0x60, p2)
9975
            mstore(0x80, p3)
9976
            writeString(0xa0, p1)
9977
        }
9978
        _sendLogPayload(0x1c, 0xc4);
9979
        /// @solidity memory-safe-assembly
9980
        assembly {
9981
            mstore(0x00, m0)
9982
            mstore(0x20, m1)
9983
            mstore(0x40, m2)
9984
            mstore(0x60, m3)
9985
            mstore(0x80, m4)
9986
            mstore(0xa0, m5)
9987
            mstore(0xc0, m6)
9988
        }
9989
    }
9990

                            
                        
9991
    function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure {
9992
        bytes32 m0;
9993
        bytes32 m1;
9994
        bytes32 m2;
9995
        bytes32 m3;
9996
        bytes32 m4;
9997
        bytes32 m5;
9998
        bytes32 m6;
9999
        /// @solidity memory-safe-assembly
10000
        assembly {
10001
            function writeString(pos, w) {
10002
                let length := 0
10003
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10004
                mstore(pos, length)
10005
                let shift := sub(256, shl(3, length))
10006
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10007
            }
10008
            m0 := mload(0x00)
10009
            m1 := mload(0x20)
10010
            m2 := mload(0x40)
10011
            m3 := mload(0x60)
10012
            m4 := mload(0x80)
10013
            m5 := mload(0xa0)
10014
            m6 := mload(0xc0)
10015
            // Selector of `log(uint256,string,address,bool)`.
10016
            mstore(0x00, 0x90c30a56)
10017
            mstore(0x20, p0)
10018
            mstore(0x40, 0x80)
10019
            mstore(0x60, p2)
10020
            mstore(0x80, p3)
10021
            writeString(0xa0, p1)
10022
        }
10023
        _sendLogPayload(0x1c, 0xc4);
10024
        /// @solidity memory-safe-assembly
10025
        assembly {
10026
            mstore(0x00, m0)
10027
            mstore(0x20, m1)
10028
            mstore(0x40, m2)
10029
            mstore(0x60, m3)
10030
            mstore(0x80, m4)
10031
            mstore(0xa0, m5)
10032
            mstore(0xc0, m6)
10033
        }
10034
    }
10035

                            
                        
10036
    function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure {
10037
        bytes32 m0;
10038
        bytes32 m1;
10039
        bytes32 m2;
10040
        bytes32 m3;
10041
        bytes32 m4;
10042
        bytes32 m5;
10043
        bytes32 m6;
10044
        /// @solidity memory-safe-assembly
10045
        assembly {
10046
            function writeString(pos, w) {
10047
                let length := 0
10048
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10049
                mstore(pos, length)
10050
                let shift := sub(256, shl(3, length))
10051
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10052
            }
10053
            m0 := mload(0x00)
10054
            m1 := mload(0x20)
10055
            m2 := mload(0x40)
10056
            m3 := mload(0x60)
10057
            m4 := mload(0x80)
10058
            m5 := mload(0xa0)
10059
            m6 := mload(0xc0)
10060
            // Selector of `log(uint256,string,address,uint256)`.
10061
            mstore(0x00, 0xe8d3018d)
10062
            mstore(0x20, p0)
10063
            mstore(0x40, 0x80)
10064
            mstore(0x60, p2)
10065
            mstore(0x80, p3)
10066
            writeString(0xa0, p1)
10067
        }
10068
        _sendLogPayload(0x1c, 0xc4);
10069
        /// @solidity memory-safe-assembly
10070
        assembly {
10071
            mstore(0x00, m0)
10072
            mstore(0x20, m1)
10073
            mstore(0x40, m2)
10074
            mstore(0x60, m3)
10075
            mstore(0x80, m4)
10076
            mstore(0xa0, m5)
10077
            mstore(0xc0, m6)
10078
        }
10079
    }
10080

                            
                        
10081
    function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
10082
        bytes32 m0;
10083
        bytes32 m1;
10084
        bytes32 m2;
10085
        bytes32 m3;
10086
        bytes32 m4;
10087
        bytes32 m5;
10088
        bytes32 m6;
10089
        bytes32 m7;
10090
        bytes32 m8;
10091
        /// @solidity memory-safe-assembly
10092
        assembly {
10093
            function writeString(pos, w) {
10094
                let length := 0
10095
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10096
                mstore(pos, length)
10097
                let shift := sub(256, shl(3, length))
10098
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10099
            }
10100
            m0 := mload(0x00)
10101
            m1 := mload(0x20)
10102
            m2 := mload(0x40)
10103
            m3 := mload(0x60)
10104
            m4 := mload(0x80)
10105
            m5 := mload(0xa0)
10106
            m6 := mload(0xc0)
10107
            m7 := mload(0xe0)
10108
            m8 := mload(0x100)
10109
            // Selector of `log(uint256,string,address,string)`.
10110
            mstore(0x00, 0x9c3adfa1)
10111
            mstore(0x20, p0)
10112
            mstore(0x40, 0x80)
10113
            mstore(0x60, p2)
10114
            mstore(0x80, 0xc0)
10115
            writeString(0xa0, p1)
10116
            writeString(0xe0, p3)
10117
        }
10118
        _sendLogPayload(0x1c, 0x104);
10119
        /// @solidity memory-safe-assembly
10120
        assembly {
10121
            mstore(0x00, m0)
10122
            mstore(0x20, m1)
10123
            mstore(0x40, m2)
10124
            mstore(0x60, m3)
10125
            mstore(0x80, m4)
10126
            mstore(0xa0, m5)
10127
            mstore(0xc0, m6)
10128
            mstore(0xe0, m7)
10129
            mstore(0x100, m8)
10130
        }
10131
    }
10132

                            
                        
10133
    function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure {
10134
        bytes32 m0;
10135
        bytes32 m1;
10136
        bytes32 m2;
10137
        bytes32 m3;
10138
        bytes32 m4;
10139
        bytes32 m5;
10140
        bytes32 m6;
10141
        /// @solidity memory-safe-assembly
10142
        assembly {
10143
            function writeString(pos, w) {
10144
                let length := 0
10145
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10146
                mstore(pos, length)
10147
                let shift := sub(256, shl(3, length))
10148
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10149
            }
10150
            m0 := mload(0x00)
10151
            m1 := mload(0x20)
10152
            m2 := mload(0x40)
10153
            m3 := mload(0x60)
10154
            m4 := mload(0x80)
10155
            m5 := mload(0xa0)
10156
            m6 := mload(0xc0)
10157
            // Selector of `log(uint256,string,bool,address)`.
10158
            mstore(0x00, 0xae2ec581)
10159
            mstore(0x20, p0)
10160
            mstore(0x40, 0x80)
10161
            mstore(0x60, p2)
10162
            mstore(0x80, p3)
10163
            writeString(0xa0, p1)
10164
        }
10165
        _sendLogPayload(0x1c, 0xc4);
10166
        /// @solidity memory-safe-assembly
10167
        assembly {
10168
            mstore(0x00, m0)
10169
            mstore(0x20, m1)
10170
            mstore(0x40, m2)
10171
            mstore(0x60, m3)
10172
            mstore(0x80, m4)
10173
            mstore(0xa0, m5)
10174
            mstore(0xc0, m6)
10175
        }
10176
    }
10177

                            
                        
10178
    function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure {
10179
        bytes32 m0;
10180
        bytes32 m1;
10181
        bytes32 m2;
10182
        bytes32 m3;
10183
        bytes32 m4;
10184
        bytes32 m5;
10185
        bytes32 m6;
10186
        /// @solidity memory-safe-assembly
10187
        assembly {
10188
            function writeString(pos, w) {
10189
                let length := 0
10190
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10191
                mstore(pos, length)
10192
                let shift := sub(256, shl(3, length))
10193
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10194
            }
10195
            m0 := mload(0x00)
10196
            m1 := mload(0x20)
10197
            m2 := mload(0x40)
10198
            m3 := mload(0x60)
10199
            m4 := mload(0x80)
10200
            m5 := mload(0xa0)
10201
            m6 := mload(0xc0)
10202
            // Selector of `log(uint256,string,bool,bool)`.
10203
            mstore(0x00, 0xba535d9c)
10204
            mstore(0x20, p0)
10205
            mstore(0x40, 0x80)
10206
            mstore(0x60, p2)
10207
            mstore(0x80, p3)
10208
            writeString(0xa0, p1)
10209
        }
10210
        _sendLogPayload(0x1c, 0xc4);
10211
        /// @solidity memory-safe-assembly
10212
        assembly {
10213
            mstore(0x00, m0)
10214
            mstore(0x20, m1)
10215
            mstore(0x40, m2)
10216
            mstore(0x60, m3)
10217
            mstore(0x80, m4)
10218
            mstore(0xa0, m5)
10219
            mstore(0xc0, m6)
10220
        }
10221
    }
10222

                            
                        
10223
    function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
10224
        bytes32 m0;
10225
        bytes32 m1;
10226
        bytes32 m2;
10227
        bytes32 m3;
10228
        bytes32 m4;
10229
        bytes32 m5;
10230
        bytes32 m6;
10231
        /// @solidity memory-safe-assembly
10232
        assembly {
10233
            function writeString(pos, w) {
10234
                let length := 0
10235
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10236
                mstore(pos, length)
10237
                let shift := sub(256, shl(3, length))
10238
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10239
            }
10240
            m0 := mload(0x00)
10241
            m1 := mload(0x20)
10242
            m2 := mload(0x40)
10243
            m3 := mload(0x60)
10244
            m4 := mload(0x80)
10245
            m5 := mload(0xa0)
10246
            m6 := mload(0xc0)
10247
            // Selector of `log(uint256,string,bool,uint256)`.
10248
            mstore(0x00, 0xcf009880)
10249
            mstore(0x20, p0)
10250
            mstore(0x40, 0x80)
10251
            mstore(0x60, p2)
10252
            mstore(0x80, p3)
10253
            writeString(0xa0, p1)
10254
        }
10255
        _sendLogPayload(0x1c, 0xc4);
10256
        /// @solidity memory-safe-assembly
10257
        assembly {
10258
            mstore(0x00, m0)
10259
            mstore(0x20, m1)
10260
            mstore(0x40, m2)
10261
            mstore(0x60, m3)
10262
            mstore(0x80, m4)
10263
            mstore(0xa0, m5)
10264
            mstore(0xc0, m6)
10265
        }
10266
    }
10267

                            
                        
10268
    function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
10269
        bytes32 m0;
10270
        bytes32 m1;
10271
        bytes32 m2;
10272
        bytes32 m3;
10273
        bytes32 m4;
10274
        bytes32 m5;
10275
        bytes32 m6;
10276
        bytes32 m7;
10277
        bytes32 m8;
10278
        /// @solidity memory-safe-assembly
10279
        assembly {
10280
            function writeString(pos, w) {
10281
                let length := 0
10282
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10283
                mstore(pos, length)
10284
                let shift := sub(256, shl(3, length))
10285
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10286
            }
10287
            m0 := mload(0x00)
10288
            m1 := mload(0x20)
10289
            m2 := mload(0x40)
10290
            m3 := mload(0x60)
10291
            m4 := mload(0x80)
10292
            m5 := mload(0xa0)
10293
            m6 := mload(0xc0)
10294
            m7 := mload(0xe0)
10295
            m8 := mload(0x100)
10296
            // Selector of `log(uint256,string,bool,string)`.
10297
            mstore(0x00, 0xd2d423cd)
10298
            mstore(0x20, p0)
10299
            mstore(0x40, 0x80)
10300
            mstore(0x60, p2)
10301
            mstore(0x80, 0xc0)
10302
            writeString(0xa0, p1)
10303
            writeString(0xe0, p3)
10304
        }
10305
        _sendLogPayload(0x1c, 0x104);
10306
        /// @solidity memory-safe-assembly
10307
        assembly {
10308
            mstore(0x00, m0)
10309
            mstore(0x20, m1)
10310
            mstore(0x40, m2)
10311
            mstore(0x60, m3)
10312
            mstore(0x80, m4)
10313
            mstore(0xa0, m5)
10314
            mstore(0xc0, m6)
10315
            mstore(0xe0, m7)
10316
            mstore(0x100, m8)
10317
        }
10318
    }
10319

                            
                        
10320
    function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure {
10321
        bytes32 m0;
10322
        bytes32 m1;
10323
        bytes32 m2;
10324
        bytes32 m3;
10325
        bytes32 m4;
10326
        bytes32 m5;
10327
        bytes32 m6;
10328
        /// @solidity memory-safe-assembly
10329
        assembly {
10330
            function writeString(pos, w) {
10331
                let length := 0
10332
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10333
                mstore(pos, length)
10334
                let shift := sub(256, shl(3, length))
10335
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10336
            }
10337
            m0 := mload(0x00)
10338
            m1 := mload(0x20)
10339
            m2 := mload(0x40)
10340
            m3 := mload(0x60)
10341
            m4 := mload(0x80)
10342
            m5 := mload(0xa0)
10343
            m6 := mload(0xc0)
10344
            // Selector of `log(uint256,string,uint256,address)`.
10345
            mstore(0x00, 0x3b2279b4)
10346
            mstore(0x20, p0)
10347
            mstore(0x40, 0x80)
10348
            mstore(0x60, p2)
10349
            mstore(0x80, p3)
10350
            writeString(0xa0, p1)
10351
        }
10352
        _sendLogPayload(0x1c, 0xc4);
10353
        /// @solidity memory-safe-assembly
10354
        assembly {
10355
            mstore(0x00, m0)
10356
            mstore(0x20, m1)
10357
            mstore(0x40, m2)
10358
            mstore(0x60, m3)
10359
            mstore(0x80, m4)
10360
            mstore(0xa0, m5)
10361
            mstore(0xc0, m6)
10362
        }
10363
    }
10364

                            
                        
10365
    function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
10366
        bytes32 m0;
10367
        bytes32 m1;
10368
        bytes32 m2;
10369
        bytes32 m3;
10370
        bytes32 m4;
10371
        bytes32 m5;
10372
        bytes32 m6;
10373
        /// @solidity memory-safe-assembly
10374
        assembly {
10375
            function writeString(pos, w) {
10376
                let length := 0
10377
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10378
                mstore(pos, length)
10379
                let shift := sub(256, shl(3, length))
10380
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10381
            }
10382
            m0 := mload(0x00)
10383
            m1 := mload(0x20)
10384
            m2 := mload(0x40)
10385
            m3 := mload(0x60)
10386
            m4 := mload(0x80)
10387
            m5 := mload(0xa0)
10388
            m6 := mload(0xc0)
10389
            // Selector of `log(uint256,string,uint256,bool)`.
10390
            mstore(0x00, 0x691a8f74)
10391
            mstore(0x20, p0)
10392
            mstore(0x40, 0x80)
10393
            mstore(0x60, p2)
10394
            mstore(0x80, p3)
10395
            writeString(0xa0, p1)
10396
        }
10397
        _sendLogPayload(0x1c, 0xc4);
10398
        /// @solidity memory-safe-assembly
10399
        assembly {
10400
            mstore(0x00, m0)
10401
            mstore(0x20, m1)
10402
            mstore(0x40, m2)
10403
            mstore(0x60, m3)
10404
            mstore(0x80, m4)
10405
            mstore(0xa0, m5)
10406
            mstore(0xc0, m6)
10407
        }
10408
    }
10409

                            
                        
10410
    function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
10411
        bytes32 m0;
10412
        bytes32 m1;
10413
        bytes32 m2;
10414
        bytes32 m3;
10415
        bytes32 m4;
10416
        bytes32 m5;
10417
        bytes32 m6;
10418
        /// @solidity memory-safe-assembly
10419
        assembly {
10420
            function writeString(pos, w) {
10421
                let length := 0
10422
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10423
                mstore(pos, length)
10424
                let shift := sub(256, shl(3, length))
10425
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10426
            }
10427
            m0 := mload(0x00)
10428
            m1 := mload(0x20)
10429
            m2 := mload(0x40)
10430
            m3 := mload(0x60)
10431
            m4 := mload(0x80)
10432
            m5 := mload(0xa0)
10433
            m6 := mload(0xc0)
10434
            // Selector of `log(uint256,string,uint256,uint256)`.
10435
            mstore(0x00, 0x82c25b74)
10436
            mstore(0x20, p0)
10437
            mstore(0x40, 0x80)
10438
            mstore(0x60, p2)
10439
            mstore(0x80, p3)
10440
            writeString(0xa0, p1)
10441
        }
10442
        _sendLogPayload(0x1c, 0xc4);
10443
        /// @solidity memory-safe-assembly
10444
        assembly {
10445
            mstore(0x00, m0)
10446
            mstore(0x20, m1)
10447
            mstore(0x40, m2)
10448
            mstore(0x60, m3)
10449
            mstore(0x80, m4)
10450
            mstore(0xa0, m5)
10451
            mstore(0xc0, m6)
10452
        }
10453
    }
10454

                            
                        
10455
    function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
10456
        bytes32 m0;
10457
        bytes32 m1;
10458
        bytes32 m2;
10459
        bytes32 m3;
10460
        bytes32 m4;
10461
        bytes32 m5;
10462
        bytes32 m6;
10463
        bytes32 m7;
10464
        bytes32 m8;
10465
        /// @solidity memory-safe-assembly
10466
        assembly {
10467
            function writeString(pos, w) {
10468
                let length := 0
10469
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10470
                mstore(pos, length)
10471
                let shift := sub(256, shl(3, length))
10472
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10473
            }
10474
            m0 := mload(0x00)
10475
            m1 := mload(0x20)
10476
            m2 := mload(0x40)
10477
            m3 := mload(0x60)
10478
            m4 := mload(0x80)
10479
            m5 := mload(0xa0)
10480
            m6 := mload(0xc0)
10481
            m7 := mload(0xe0)
10482
            m8 := mload(0x100)
10483
            // Selector of `log(uint256,string,uint256,string)`.
10484
            mstore(0x00, 0xb7b914ca)
10485
            mstore(0x20, p0)
10486
            mstore(0x40, 0x80)
10487
            mstore(0x60, p2)
10488
            mstore(0x80, 0xc0)
10489
            writeString(0xa0, p1)
10490
            writeString(0xe0, p3)
10491
        }
10492
        _sendLogPayload(0x1c, 0x104);
10493
        /// @solidity memory-safe-assembly
10494
        assembly {
10495
            mstore(0x00, m0)
10496
            mstore(0x20, m1)
10497
            mstore(0x40, m2)
10498
            mstore(0x60, m3)
10499
            mstore(0x80, m4)
10500
            mstore(0xa0, m5)
10501
            mstore(0xc0, m6)
10502
            mstore(0xe0, m7)
10503
            mstore(0x100, m8)
10504
        }
10505
    }
10506

                            
                        
10507
    function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
10508
        bytes32 m0;
10509
        bytes32 m1;
10510
        bytes32 m2;
10511
        bytes32 m3;
10512
        bytes32 m4;
10513
        bytes32 m5;
10514
        bytes32 m6;
10515
        bytes32 m7;
10516
        bytes32 m8;
10517
        /// @solidity memory-safe-assembly
10518
        assembly {
10519
            function writeString(pos, w) {
10520
                let length := 0
10521
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10522
                mstore(pos, length)
10523
                let shift := sub(256, shl(3, length))
10524
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10525
            }
10526
            m0 := mload(0x00)
10527
            m1 := mload(0x20)
10528
            m2 := mload(0x40)
10529
            m3 := mload(0x60)
10530
            m4 := mload(0x80)
10531
            m5 := mload(0xa0)
10532
            m6 := mload(0xc0)
10533
            m7 := mload(0xe0)
10534
            m8 := mload(0x100)
10535
            // Selector of `log(uint256,string,string,address)`.
10536
            mstore(0x00, 0xd583c602)
10537
            mstore(0x20, p0)
10538
            mstore(0x40, 0x80)
10539
            mstore(0x60, 0xc0)
10540
            mstore(0x80, p3)
10541
            writeString(0xa0, p1)
10542
            writeString(0xe0, p2)
10543
        }
10544
        _sendLogPayload(0x1c, 0x104);
10545
        /// @solidity memory-safe-assembly
10546
        assembly {
10547
            mstore(0x00, m0)
10548
            mstore(0x20, m1)
10549
            mstore(0x40, m2)
10550
            mstore(0x60, m3)
10551
            mstore(0x80, m4)
10552
            mstore(0xa0, m5)
10553
            mstore(0xc0, m6)
10554
            mstore(0xe0, m7)
10555
            mstore(0x100, m8)
10556
        }
10557
    }
10558

                            
                        
10559
    function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
10560
        bytes32 m0;
10561
        bytes32 m1;
10562
        bytes32 m2;
10563
        bytes32 m3;
10564
        bytes32 m4;
10565
        bytes32 m5;
10566
        bytes32 m6;
10567
        bytes32 m7;
10568
        bytes32 m8;
10569
        /// @solidity memory-safe-assembly
10570
        assembly {
10571
            function writeString(pos, w) {
10572
                let length := 0
10573
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10574
                mstore(pos, length)
10575
                let shift := sub(256, shl(3, length))
10576
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10577
            }
10578
            m0 := mload(0x00)
10579
            m1 := mload(0x20)
10580
            m2 := mload(0x40)
10581
            m3 := mload(0x60)
10582
            m4 := mload(0x80)
10583
            m5 := mload(0xa0)
10584
            m6 := mload(0xc0)
10585
            m7 := mload(0xe0)
10586
            m8 := mload(0x100)
10587
            // Selector of `log(uint256,string,string,bool)`.
10588
            mstore(0x00, 0xb3a6b6bd)
10589
            mstore(0x20, p0)
10590
            mstore(0x40, 0x80)
10591
            mstore(0x60, 0xc0)
10592
            mstore(0x80, p3)
10593
            writeString(0xa0, p1)
10594
            writeString(0xe0, p2)
10595
        }
10596
        _sendLogPayload(0x1c, 0x104);
10597
        /// @solidity memory-safe-assembly
10598
        assembly {
10599
            mstore(0x00, m0)
10600
            mstore(0x20, m1)
10601
            mstore(0x40, m2)
10602
            mstore(0x60, m3)
10603
            mstore(0x80, m4)
10604
            mstore(0xa0, m5)
10605
            mstore(0xc0, m6)
10606
            mstore(0xe0, m7)
10607
            mstore(0x100, m8)
10608
        }
10609
    }
10610

                            
                        
10611
    function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
10612
        bytes32 m0;
10613
        bytes32 m1;
10614
        bytes32 m2;
10615
        bytes32 m3;
10616
        bytes32 m4;
10617
        bytes32 m5;
10618
        bytes32 m6;
10619
        bytes32 m7;
10620
        bytes32 m8;
10621
        /// @solidity memory-safe-assembly
10622
        assembly {
10623
            function writeString(pos, w) {
10624
                let length := 0
10625
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10626
                mstore(pos, length)
10627
                let shift := sub(256, shl(3, length))
10628
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10629
            }
10630
            m0 := mload(0x00)
10631
            m1 := mload(0x20)
10632
            m2 := mload(0x40)
10633
            m3 := mload(0x60)
10634
            m4 := mload(0x80)
10635
            m5 := mload(0xa0)
10636
            m6 := mload(0xc0)
10637
            m7 := mload(0xe0)
10638
            m8 := mload(0x100)
10639
            // Selector of `log(uint256,string,string,uint256)`.
10640
            mstore(0x00, 0xb028c9bd)
10641
            mstore(0x20, p0)
10642
            mstore(0x40, 0x80)
10643
            mstore(0x60, 0xc0)
10644
            mstore(0x80, p3)
10645
            writeString(0xa0, p1)
10646
            writeString(0xe0, p2)
10647
        }
10648
        _sendLogPayload(0x1c, 0x104);
10649
        /// @solidity memory-safe-assembly
10650
        assembly {
10651
            mstore(0x00, m0)
10652
            mstore(0x20, m1)
10653
            mstore(0x40, m2)
10654
            mstore(0x60, m3)
10655
            mstore(0x80, m4)
10656
            mstore(0xa0, m5)
10657
            mstore(0xc0, m6)
10658
            mstore(0xe0, m7)
10659
            mstore(0x100, m8)
10660
        }
10661
    }
10662

                            
                        
10663
    function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
10664
        bytes32 m0;
10665
        bytes32 m1;
10666
        bytes32 m2;
10667
        bytes32 m3;
10668
        bytes32 m4;
10669
        bytes32 m5;
10670
        bytes32 m6;
10671
        bytes32 m7;
10672
        bytes32 m8;
10673
        bytes32 m9;
10674
        bytes32 m10;
10675
        /// @solidity memory-safe-assembly
10676
        assembly {
10677
            function writeString(pos, w) {
10678
                let length := 0
10679
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10680
                mstore(pos, length)
10681
                let shift := sub(256, shl(3, length))
10682
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10683
            }
10684
            m0 := mload(0x00)
10685
            m1 := mload(0x20)
10686
            m2 := mload(0x40)
10687
            m3 := mload(0x60)
10688
            m4 := mload(0x80)
10689
            m5 := mload(0xa0)
10690
            m6 := mload(0xc0)
10691
            m7 := mload(0xe0)
10692
            m8 := mload(0x100)
10693
            m9 := mload(0x120)
10694
            m10 := mload(0x140)
10695
            // Selector of `log(uint256,string,string,string)`.
10696
            mstore(0x00, 0x21ad0683)
10697
            mstore(0x20, p0)
10698
            mstore(0x40, 0x80)
10699
            mstore(0x60, 0xc0)
10700
            mstore(0x80, 0x100)
10701
            writeString(0xa0, p1)
10702
            writeString(0xe0, p2)
10703
            writeString(0x120, p3)
10704
        }
10705
        _sendLogPayload(0x1c, 0x144);
10706
        /// @solidity memory-safe-assembly
10707
        assembly {
10708
            mstore(0x00, m0)
10709
            mstore(0x20, m1)
10710
            mstore(0x40, m2)
10711
            mstore(0x60, m3)
10712
            mstore(0x80, m4)
10713
            mstore(0xa0, m5)
10714
            mstore(0xc0, m6)
10715
            mstore(0xe0, m7)
10716
            mstore(0x100, m8)
10717
            mstore(0x120, m9)
10718
            mstore(0x140, m10)
10719
        }
10720
    }
10721

                            
                        
10722
    function log(bytes32 p0, address p1, address p2, address p3) internal pure {
10723
        bytes32 m0;
10724
        bytes32 m1;
10725
        bytes32 m2;
10726
        bytes32 m3;
10727
        bytes32 m4;
10728
        bytes32 m5;
10729
        bytes32 m6;
10730
        /// @solidity memory-safe-assembly
10731
        assembly {
10732
            function writeString(pos, w) {
10733
                let length := 0
10734
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10735
                mstore(pos, length)
10736
                let shift := sub(256, shl(3, length))
10737
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10738
            }
10739
            m0 := mload(0x00)
10740
            m1 := mload(0x20)
10741
            m2 := mload(0x40)
10742
            m3 := mload(0x60)
10743
            m4 := mload(0x80)
10744
            m5 := mload(0xa0)
10745
            m6 := mload(0xc0)
10746
            // Selector of `log(string,address,address,address)`.
10747
            mstore(0x00, 0xed8f28f6)
10748
            mstore(0x20, 0x80)
10749
            mstore(0x40, p1)
10750
            mstore(0x60, p2)
10751
            mstore(0x80, p3)
10752
            writeString(0xa0, p0)
10753
        }
10754
        _sendLogPayload(0x1c, 0xc4);
10755
        /// @solidity memory-safe-assembly
10756
        assembly {
10757
            mstore(0x00, m0)
10758
            mstore(0x20, m1)
10759
            mstore(0x40, m2)
10760
            mstore(0x60, m3)
10761
            mstore(0x80, m4)
10762
            mstore(0xa0, m5)
10763
            mstore(0xc0, m6)
10764
        }
10765
    }
10766

                            
                        
10767
    function log(bytes32 p0, address p1, address p2, bool p3) internal pure {
10768
        bytes32 m0;
10769
        bytes32 m1;
10770
        bytes32 m2;
10771
        bytes32 m3;
10772
        bytes32 m4;
10773
        bytes32 m5;
10774
        bytes32 m6;
10775
        /// @solidity memory-safe-assembly
10776
        assembly {
10777
            function writeString(pos, w) {
10778
                let length := 0
10779
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10780
                mstore(pos, length)
10781
                let shift := sub(256, shl(3, length))
10782
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10783
            }
10784
            m0 := mload(0x00)
10785
            m1 := mload(0x20)
10786
            m2 := mload(0x40)
10787
            m3 := mload(0x60)
10788
            m4 := mload(0x80)
10789
            m5 := mload(0xa0)
10790
            m6 := mload(0xc0)
10791
            // Selector of `log(string,address,address,bool)`.
10792
            mstore(0x00, 0xb59dbd60)
10793
            mstore(0x20, 0x80)
10794
            mstore(0x40, p1)
10795
            mstore(0x60, p2)
10796
            mstore(0x80, p3)
10797
            writeString(0xa0, p0)
10798
        }
10799
        _sendLogPayload(0x1c, 0xc4);
10800
        /// @solidity memory-safe-assembly
10801
        assembly {
10802
            mstore(0x00, m0)
10803
            mstore(0x20, m1)
10804
            mstore(0x40, m2)
10805
            mstore(0x60, m3)
10806
            mstore(0x80, m4)
10807
            mstore(0xa0, m5)
10808
            mstore(0xc0, m6)
10809
        }
10810
    }
10811

                            
                        
10812
    function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure {
10813
        bytes32 m0;
10814
        bytes32 m1;
10815
        bytes32 m2;
10816
        bytes32 m3;
10817
        bytes32 m4;
10818
        bytes32 m5;
10819
        bytes32 m6;
10820
        /// @solidity memory-safe-assembly
10821
        assembly {
10822
            function writeString(pos, w) {
10823
                let length := 0
10824
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10825
                mstore(pos, length)
10826
                let shift := sub(256, shl(3, length))
10827
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10828
            }
10829
            m0 := mload(0x00)
10830
            m1 := mload(0x20)
10831
            m2 := mload(0x40)
10832
            m3 := mload(0x60)
10833
            m4 := mload(0x80)
10834
            m5 := mload(0xa0)
10835
            m6 := mload(0xc0)
10836
            // Selector of `log(string,address,address,uint256)`.
10837
            mstore(0x00, 0x8ef3f399)
10838
            mstore(0x20, 0x80)
10839
            mstore(0x40, p1)
10840
            mstore(0x60, p2)
10841
            mstore(0x80, p3)
10842
            writeString(0xa0, p0)
10843
        }
10844
        _sendLogPayload(0x1c, 0xc4);
10845
        /// @solidity memory-safe-assembly
10846
        assembly {
10847
            mstore(0x00, m0)
10848
            mstore(0x20, m1)
10849
            mstore(0x40, m2)
10850
            mstore(0x60, m3)
10851
            mstore(0x80, m4)
10852
            mstore(0xa0, m5)
10853
            mstore(0xc0, m6)
10854
        }
10855
    }
10856

                            
                        
10857
    function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure {
10858
        bytes32 m0;
10859
        bytes32 m1;
10860
        bytes32 m2;
10861
        bytes32 m3;
10862
        bytes32 m4;
10863
        bytes32 m5;
10864
        bytes32 m6;
10865
        bytes32 m7;
10866
        bytes32 m8;
10867
        /// @solidity memory-safe-assembly
10868
        assembly {
10869
            function writeString(pos, w) {
10870
                let length := 0
10871
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10872
                mstore(pos, length)
10873
                let shift := sub(256, shl(3, length))
10874
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10875
            }
10876
            m0 := mload(0x00)
10877
            m1 := mload(0x20)
10878
            m2 := mload(0x40)
10879
            m3 := mload(0x60)
10880
            m4 := mload(0x80)
10881
            m5 := mload(0xa0)
10882
            m6 := mload(0xc0)
10883
            m7 := mload(0xe0)
10884
            m8 := mload(0x100)
10885
            // Selector of `log(string,address,address,string)`.
10886
            mstore(0x00, 0x800a1c67)
10887
            mstore(0x20, 0x80)
10888
            mstore(0x40, p1)
10889
            mstore(0x60, p2)
10890
            mstore(0x80, 0xc0)
10891
            writeString(0xa0, p0)
10892
            writeString(0xe0, p3)
10893
        }
10894
        _sendLogPayload(0x1c, 0x104);
10895
        /// @solidity memory-safe-assembly
10896
        assembly {
10897
            mstore(0x00, m0)
10898
            mstore(0x20, m1)
10899
            mstore(0x40, m2)
10900
            mstore(0x60, m3)
10901
            mstore(0x80, m4)
10902
            mstore(0xa0, m5)
10903
            mstore(0xc0, m6)
10904
            mstore(0xe0, m7)
10905
            mstore(0x100, m8)
10906
        }
10907
    }
10908

                            
                        
10909
    function log(bytes32 p0, address p1, bool p2, address p3) internal pure {
10910
        bytes32 m0;
10911
        bytes32 m1;
10912
        bytes32 m2;
10913
        bytes32 m3;
10914
        bytes32 m4;
10915
        bytes32 m5;
10916
        bytes32 m6;
10917
        /// @solidity memory-safe-assembly
10918
        assembly {
10919
            function writeString(pos, w) {
10920
                let length := 0
10921
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10922
                mstore(pos, length)
10923
                let shift := sub(256, shl(3, length))
10924
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10925
            }
10926
            m0 := mload(0x00)
10927
            m1 := mload(0x20)
10928
            m2 := mload(0x40)
10929
            m3 := mload(0x60)
10930
            m4 := mload(0x80)
10931
            m5 := mload(0xa0)
10932
            m6 := mload(0xc0)
10933
            // Selector of `log(string,address,bool,address)`.
10934
            mstore(0x00, 0x223603bd)
10935
            mstore(0x20, 0x80)
10936
            mstore(0x40, p1)
10937
            mstore(0x60, p2)
10938
            mstore(0x80, p3)
10939
            writeString(0xa0, p0)
10940
        }
10941
        _sendLogPayload(0x1c, 0xc4);
10942
        /// @solidity memory-safe-assembly
10943
        assembly {
10944
            mstore(0x00, m0)
10945
            mstore(0x20, m1)
10946
            mstore(0x40, m2)
10947
            mstore(0x60, m3)
10948
            mstore(0x80, m4)
10949
            mstore(0xa0, m5)
10950
            mstore(0xc0, m6)
10951
        }
10952
    }
10953

                            
                        
10954
    function log(bytes32 p0, address p1, bool p2, bool p3) internal pure {
10955
        bytes32 m0;
10956
        bytes32 m1;
10957
        bytes32 m2;
10958
        bytes32 m3;
10959
        bytes32 m4;
10960
        bytes32 m5;
10961
        bytes32 m6;
10962
        /// @solidity memory-safe-assembly
10963
        assembly {
10964
            function writeString(pos, w) {
10965
                let length := 0
10966
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
10967
                mstore(pos, length)
10968
                let shift := sub(256, shl(3, length))
10969
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
10970
            }
10971
            m0 := mload(0x00)
10972
            m1 := mload(0x20)
10973
            m2 := mload(0x40)
10974
            m3 := mload(0x60)
10975
            m4 := mload(0x80)
10976
            m5 := mload(0xa0)
10977
            m6 := mload(0xc0)
10978
            // Selector of `log(string,address,bool,bool)`.
10979
            mstore(0x00, 0x79884c2b)
10980
            mstore(0x20, 0x80)
10981
            mstore(0x40, p1)
10982
            mstore(0x60, p2)
10983
            mstore(0x80, p3)
10984
            writeString(0xa0, p0)
10985
        }
10986
        _sendLogPayload(0x1c, 0xc4);
10987
        /// @solidity memory-safe-assembly
10988
        assembly {
10989
            mstore(0x00, m0)
10990
            mstore(0x20, m1)
10991
            mstore(0x40, m2)
10992
            mstore(0x60, m3)
10993
            mstore(0x80, m4)
10994
            mstore(0xa0, m5)
10995
            mstore(0xc0, m6)
10996
        }
10997
    }
10998

                            
                        
10999
    function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure {
11000
        bytes32 m0;
11001
        bytes32 m1;
11002
        bytes32 m2;
11003
        bytes32 m3;
11004
        bytes32 m4;
11005
        bytes32 m5;
11006
        bytes32 m6;
11007
        /// @solidity memory-safe-assembly
11008
        assembly {
11009
            function writeString(pos, w) {
11010
                let length := 0
11011
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11012
                mstore(pos, length)
11013
                let shift := sub(256, shl(3, length))
11014
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11015
            }
11016
            m0 := mload(0x00)
11017
            m1 := mload(0x20)
11018
            m2 := mload(0x40)
11019
            m3 := mload(0x60)
11020
            m4 := mload(0x80)
11021
            m5 := mload(0xa0)
11022
            m6 := mload(0xc0)
11023
            // Selector of `log(string,address,bool,uint256)`.
11024
            mstore(0x00, 0x3e9f866a)
11025
            mstore(0x20, 0x80)
11026
            mstore(0x40, p1)
11027
            mstore(0x60, p2)
11028
            mstore(0x80, p3)
11029
            writeString(0xa0, p0)
11030
        }
11031
        _sendLogPayload(0x1c, 0xc4);
11032
        /// @solidity memory-safe-assembly
11033
        assembly {
11034
            mstore(0x00, m0)
11035
            mstore(0x20, m1)
11036
            mstore(0x40, m2)
11037
            mstore(0x60, m3)
11038
            mstore(0x80, m4)
11039
            mstore(0xa0, m5)
11040
            mstore(0xc0, m6)
11041
        }
11042
    }
11043

                            
                        
11044
    function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure {
11045
        bytes32 m0;
11046
        bytes32 m1;
11047
        bytes32 m2;
11048
        bytes32 m3;
11049
        bytes32 m4;
11050
        bytes32 m5;
11051
        bytes32 m6;
11052
        bytes32 m7;
11053
        bytes32 m8;
11054
        /// @solidity memory-safe-assembly
11055
        assembly {
11056
            function writeString(pos, w) {
11057
                let length := 0
11058
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11059
                mstore(pos, length)
11060
                let shift := sub(256, shl(3, length))
11061
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11062
            }
11063
            m0 := mload(0x00)
11064
            m1 := mload(0x20)
11065
            m2 := mload(0x40)
11066
            m3 := mload(0x60)
11067
            m4 := mload(0x80)
11068
            m5 := mload(0xa0)
11069
            m6 := mload(0xc0)
11070
            m7 := mload(0xe0)
11071
            m8 := mload(0x100)
11072
            // Selector of `log(string,address,bool,string)`.
11073
            mstore(0x00, 0x0454c079)
11074
            mstore(0x20, 0x80)
11075
            mstore(0x40, p1)
11076
            mstore(0x60, p2)
11077
            mstore(0x80, 0xc0)
11078
            writeString(0xa0, p0)
11079
            writeString(0xe0, p3)
11080
        }
11081
        _sendLogPayload(0x1c, 0x104);
11082
        /// @solidity memory-safe-assembly
11083
        assembly {
11084
            mstore(0x00, m0)
11085
            mstore(0x20, m1)
11086
            mstore(0x40, m2)
11087
            mstore(0x60, m3)
11088
            mstore(0x80, m4)
11089
            mstore(0xa0, m5)
11090
            mstore(0xc0, m6)
11091
            mstore(0xe0, m7)
11092
            mstore(0x100, m8)
11093
        }
11094
    }
11095

                            
                        
11096
    function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure {
11097
        bytes32 m0;
11098
        bytes32 m1;
11099
        bytes32 m2;
11100
        bytes32 m3;
11101
        bytes32 m4;
11102
        bytes32 m5;
11103
        bytes32 m6;
11104
        /// @solidity memory-safe-assembly
11105
        assembly {
11106
            function writeString(pos, w) {
11107
                let length := 0
11108
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11109
                mstore(pos, length)
11110
                let shift := sub(256, shl(3, length))
11111
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11112
            }
11113
            m0 := mload(0x00)
11114
            m1 := mload(0x20)
11115
            m2 := mload(0x40)
11116
            m3 := mload(0x60)
11117
            m4 := mload(0x80)
11118
            m5 := mload(0xa0)
11119
            m6 := mload(0xc0)
11120
            // Selector of `log(string,address,uint256,address)`.
11121
            mstore(0x00, 0x63fb8bc5)
11122
            mstore(0x20, 0x80)
11123
            mstore(0x40, p1)
11124
            mstore(0x60, p2)
11125
            mstore(0x80, p3)
11126
            writeString(0xa0, p0)
11127
        }
11128
        _sendLogPayload(0x1c, 0xc4);
11129
        /// @solidity memory-safe-assembly
11130
        assembly {
11131
            mstore(0x00, m0)
11132
            mstore(0x20, m1)
11133
            mstore(0x40, m2)
11134
            mstore(0x60, m3)
11135
            mstore(0x80, m4)
11136
            mstore(0xa0, m5)
11137
            mstore(0xc0, m6)
11138
        }
11139
    }
11140

                            
                        
11141
    function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure {
11142
        bytes32 m0;
11143
        bytes32 m1;
11144
        bytes32 m2;
11145
        bytes32 m3;
11146
        bytes32 m4;
11147
        bytes32 m5;
11148
        bytes32 m6;
11149
        /// @solidity memory-safe-assembly
11150
        assembly {
11151
            function writeString(pos, w) {
11152
                let length := 0
11153
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11154
                mstore(pos, length)
11155
                let shift := sub(256, shl(3, length))
11156
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11157
            }
11158
            m0 := mload(0x00)
11159
            m1 := mload(0x20)
11160
            m2 := mload(0x40)
11161
            m3 := mload(0x60)
11162
            m4 := mload(0x80)
11163
            m5 := mload(0xa0)
11164
            m6 := mload(0xc0)
11165
            // Selector of `log(string,address,uint256,bool)`.
11166
            mstore(0x00, 0xfc4845f0)
11167
            mstore(0x20, 0x80)
11168
            mstore(0x40, p1)
11169
            mstore(0x60, p2)
11170
            mstore(0x80, p3)
11171
            writeString(0xa0, p0)
11172
        }
11173
        _sendLogPayload(0x1c, 0xc4);
11174
        /// @solidity memory-safe-assembly
11175
        assembly {
11176
            mstore(0x00, m0)
11177
            mstore(0x20, m1)
11178
            mstore(0x40, m2)
11179
            mstore(0x60, m3)
11180
            mstore(0x80, m4)
11181
            mstore(0xa0, m5)
11182
            mstore(0xc0, m6)
11183
        }
11184
    }
11185

                            
                        
11186
    function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure {
11187
        bytes32 m0;
11188
        bytes32 m1;
11189
        bytes32 m2;
11190
        bytes32 m3;
11191
        bytes32 m4;
11192
        bytes32 m5;
11193
        bytes32 m6;
11194
        /// @solidity memory-safe-assembly
11195
        assembly {
11196
            function writeString(pos, w) {
11197
                let length := 0
11198
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11199
                mstore(pos, length)
11200
                let shift := sub(256, shl(3, length))
11201
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11202
            }
11203
            m0 := mload(0x00)
11204
            m1 := mload(0x20)
11205
            m2 := mload(0x40)
11206
            m3 := mload(0x60)
11207
            m4 := mload(0x80)
11208
            m5 := mload(0xa0)
11209
            m6 := mload(0xc0)
11210
            // Selector of `log(string,address,uint256,uint256)`.
11211
            mstore(0x00, 0xf8f51b1e)
11212
            mstore(0x20, 0x80)
11213
            mstore(0x40, p1)
11214
            mstore(0x60, p2)
11215
            mstore(0x80, p3)
11216
            writeString(0xa0, p0)
11217
        }
11218
        _sendLogPayload(0x1c, 0xc4);
11219
        /// @solidity memory-safe-assembly
11220
        assembly {
11221
            mstore(0x00, m0)
11222
            mstore(0x20, m1)
11223
            mstore(0x40, m2)
11224
            mstore(0x60, m3)
11225
            mstore(0x80, m4)
11226
            mstore(0xa0, m5)
11227
            mstore(0xc0, m6)
11228
        }
11229
    }
11230

                            
                        
11231
    function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure {
11232
        bytes32 m0;
11233
        bytes32 m1;
11234
        bytes32 m2;
11235
        bytes32 m3;
11236
        bytes32 m4;
11237
        bytes32 m5;
11238
        bytes32 m6;
11239
        bytes32 m7;
11240
        bytes32 m8;
11241
        /// @solidity memory-safe-assembly
11242
        assembly {
11243
            function writeString(pos, w) {
11244
                let length := 0
11245
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11246
                mstore(pos, length)
11247
                let shift := sub(256, shl(3, length))
11248
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11249
            }
11250
            m0 := mload(0x00)
11251
            m1 := mload(0x20)
11252
            m2 := mload(0x40)
11253
            m3 := mload(0x60)
11254
            m4 := mload(0x80)
11255
            m5 := mload(0xa0)
11256
            m6 := mload(0xc0)
11257
            m7 := mload(0xe0)
11258
            m8 := mload(0x100)
11259
            // Selector of `log(string,address,uint256,string)`.
11260
            mstore(0x00, 0x5a477632)
11261
            mstore(0x20, 0x80)
11262
            mstore(0x40, p1)
11263
            mstore(0x60, p2)
11264
            mstore(0x80, 0xc0)
11265
            writeString(0xa0, p0)
11266
            writeString(0xe0, p3)
11267
        }
11268
        _sendLogPayload(0x1c, 0x104);
11269
        /// @solidity memory-safe-assembly
11270
        assembly {
11271
            mstore(0x00, m0)
11272
            mstore(0x20, m1)
11273
            mstore(0x40, m2)
11274
            mstore(0x60, m3)
11275
            mstore(0x80, m4)
11276
            mstore(0xa0, m5)
11277
            mstore(0xc0, m6)
11278
            mstore(0xe0, m7)
11279
            mstore(0x100, m8)
11280
        }
11281
    }
11282

                            
                        
11283
    function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure {
11284
        bytes32 m0;
11285
        bytes32 m1;
11286
        bytes32 m2;
11287
        bytes32 m3;
11288
        bytes32 m4;
11289
        bytes32 m5;
11290
        bytes32 m6;
11291
        bytes32 m7;
11292
        bytes32 m8;
11293
        /// @solidity memory-safe-assembly
11294
        assembly {
11295
            function writeString(pos, w) {
11296
                let length := 0
11297
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11298
                mstore(pos, length)
11299
                let shift := sub(256, shl(3, length))
11300
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11301
            }
11302
            m0 := mload(0x00)
11303
            m1 := mload(0x20)
11304
            m2 := mload(0x40)
11305
            m3 := mload(0x60)
11306
            m4 := mload(0x80)
11307
            m5 := mload(0xa0)
11308
            m6 := mload(0xc0)
11309
            m7 := mload(0xe0)
11310
            m8 := mload(0x100)
11311
            // Selector of `log(string,address,string,address)`.
11312
            mstore(0x00, 0xaabc9a31)
11313
            mstore(0x20, 0x80)
11314
            mstore(0x40, p1)
11315
            mstore(0x60, 0xc0)
11316
            mstore(0x80, p3)
11317
            writeString(0xa0, p0)
11318
            writeString(0xe0, p2)
11319
        }
11320
        _sendLogPayload(0x1c, 0x104);
11321
        /// @solidity memory-safe-assembly
11322
        assembly {
11323
            mstore(0x00, m0)
11324
            mstore(0x20, m1)
11325
            mstore(0x40, m2)
11326
            mstore(0x60, m3)
11327
            mstore(0x80, m4)
11328
            mstore(0xa0, m5)
11329
            mstore(0xc0, m6)
11330
            mstore(0xe0, m7)
11331
            mstore(0x100, m8)
11332
        }
11333
    }
11334

                            
                        
11335
    function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure {
11336
        bytes32 m0;
11337
        bytes32 m1;
11338
        bytes32 m2;
11339
        bytes32 m3;
11340
        bytes32 m4;
11341
        bytes32 m5;
11342
        bytes32 m6;
11343
        bytes32 m7;
11344
        bytes32 m8;
11345
        /// @solidity memory-safe-assembly
11346
        assembly {
11347
            function writeString(pos, w) {
11348
                let length := 0
11349
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11350
                mstore(pos, length)
11351
                let shift := sub(256, shl(3, length))
11352
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11353
            }
11354
            m0 := mload(0x00)
11355
            m1 := mload(0x20)
11356
            m2 := mload(0x40)
11357
            m3 := mload(0x60)
11358
            m4 := mload(0x80)
11359
            m5 := mload(0xa0)
11360
            m6 := mload(0xc0)
11361
            m7 := mload(0xe0)
11362
            m8 := mload(0x100)
11363
            // Selector of `log(string,address,string,bool)`.
11364
            mstore(0x00, 0x5f15d28c)
11365
            mstore(0x20, 0x80)
11366
            mstore(0x40, p1)
11367
            mstore(0x60, 0xc0)
11368
            mstore(0x80, p3)
11369
            writeString(0xa0, p0)
11370
            writeString(0xe0, p2)
11371
        }
11372
        _sendLogPayload(0x1c, 0x104);
11373
        /// @solidity memory-safe-assembly
11374
        assembly {
11375
            mstore(0x00, m0)
11376
            mstore(0x20, m1)
11377
            mstore(0x40, m2)
11378
            mstore(0x60, m3)
11379
            mstore(0x80, m4)
11380
            mstore(0xa0, m5)
11381
            mstore(0xc0, m6)
11382
            mstore(0xe0, m7)
11383
            mstore(0x100, m8)
11384
        }
11385
    }
11386

                            
                        
11387
    function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure {
11388
        bytes32 m0;
11389
        bytes32 m1;
11390
        bytes32 m2;
11391
        bytes32 m3;
11392
        bytes32 m4;
11393
        bytes32 m5;
11394
        bytes32 m6;
11395
        bytes32 m7;
11396
        bytes32 m8;
11397
        /// @solidity memory-safe-assembly
11398
        assembly {
11399
            function writeString(pos, w) {
11400
                let length := 0
11401
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11402
                mstore(pos, length)
11403
                let shift := sub(256, shl(3, length))
11404
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11405
            }
11406
            m0 := mload(0x00)
11407
            m1 := mload(0x20)
11408
            m2 := mload(0x40)
11409
            m3 := mload(0x60)
11410
            m4 := mload(0x80)
11411
            m5 := mload(0xa0)
11412
            m6 := mload(0xc0)
11413
            m7 := mload(0xe0)
11414
            m8 := mload(0x100)
11415
            // Selector of `log(string,address,string,uint256)`.
11416
            mstore(0x00, 0x91d1112e)
11417
            mstore(0x20, 0x80)
11418
            mstore(0x40, p1)
11419
            mstore(0x60, 0xc0)
11420
            mstore(0x80, p3)
11421
            writeString(0xa0, p0)
11422
            writeString(0xe0, p2)
11423
        }
11424
        _sendLogPayload(0x1c, 0x104);
11425
        /// @solidity memory-safe-assembly
11426
        assembly {
11427
            mstore(0x00, m0)
11428
            mstore(0x20, m1)
11429
            mstore(0x40, m2)
11430
            mstore(0x60, m3)
11431
            mstore(0x80, m4)
11432
            mstore(0xa0, m5)
11433
            mstore(0xc0, m6)
11434
            mstore(0xe0, m7)
11435
            mstore(0x100, m8)
11436
        }
11437
    }
11438

                            
                        
11439
    function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
11440
        bytes32 m0;
11441
        bytes32 m1;
11442
        bytes32 m2;
11443
        bytes32 m3;
11444
        bytes32 m4;
11445
        bytes32 m5;
11446
        bytes32 m6;
11447
        bytes32 m7;
11448
        bytes32 m8;
11449
        bytes32 m9;
11450
        bytes32 m10;
11451
        /// @solidity memory-safe-assembly
11452
        assembly {
11453
            function writeString(pos, w) {
11454
                let length := 0
11455
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11456
                mstore(pos, length)
11457
                let shift := sub(256, shl(3, length))
11458
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11459
            }
11460
            m0 := mload(0x00)
11461
            m1 := mload(0x20)
11462
            m2 := mload(0x40)
11463
            m3 := mload(0x60)
11464
            m4 := mload(0x80)
11465
            m5 := mload(0xa0)
11466
            m6 := mload(0xc0)
11467
            m7 := mload(0xe0)
11468
            m8 := mload(0x100)
11469
            m9 := mload(0x120)
11470
            m10 := mload(0x140)
11471
            // Selector of `log(string,address,string,string)`.
11472
            mstore(0x00, 0x245986f2)
11473
            mstore(0x20, 0x80)
11474
            mstore(0x40, p1)
11475
            mstore(0x60, 0xc0)
11476
            mstore(0x80, 0x100)
11477
            writeString(0xa0, p0)
11478
            writeString(0xe0, p2)
11479
            writeString(0x120, p3)
11480
        }
11481
        _sendLogPayload(0x1c, 0x144);
11482
        /// @solidity memory-safe-assembly
11483
        assembly {
11484
            mstore(0x00, m0)
11485
            mstore(0x20, m1)
11486
            mstore(0x40, m2)
11487
            mstore(0x60, m3)
11488
            mstore(0x80, m4)
11489
            mstore(0xa0, m5)
11490
            mstore(0xc0, m6)
11491
            mstore(0xe0, m7)
11492
            mstore(0x100, m8)
11493
            mstore(0x120, m9)
11494
            mstore(0x140, m10)
11495
        }
11496
    }
11497

                            
                        
11498
    function log(bytes32 p0, bool p1, address p2, address p3) internal pure {
11499
        bytes32 m0;
11500
        bytes32 m1;
11501
        bytes32 m2;
11502
        bytes32 m3;
11503
        bytes32 m4;
11504
        bytes32 m5;
11505
        bytes32 m6;
11506
        /// @solidity memory-safe-assembly
11507
        assembly {
11508
            function writeString(pos, w) {
11509
                let length := 0
11510
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11511
                mstore(pos, length)
11512
                let shift := sub(256, shl(3, length))
11513
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11514
            }
11515
            m0 := mload(0x00)
11516
            m1 := mload(0x20)
11517
            m2 := mload(0x40)
11518
            m3 := mload(0x60)
11519
            m4 := mload(0x80)
11520
            m5 := mload(0xa0)
11521
            m6 := mload(0xc0)
11522
            // Selector of `log(string,bool,address,address)`.
11523
            mstore(0x00, 0x33e9dd1d)
11524
            mstore(0x20, 0x80)
11525
            mstore(0x40, p1)
11526
            mstore(0x60, p2)
11527
            mstore(0x80, p3)
11528
            writeString(0xa0, p0)
11529
        }
11530
        _sendLogPayload(0x1c, 0xc4);
11531
        /// @solidity memory-safe-assembly
11532
        assembly {
11533
            mstore(0x00, m0)
11534
            mstore(0x20, m1)
11535
            mstore(0x40, m2)
11536
            mstore(0x60, m3)
11537
            mstore(0x80, m4)
11538
            mstore(0xa0, m5)
11539
            mstore(0xc0, m6)
11540
        }
11541
    }
11542

                            
                        
11543
    function log(bytes32 p0, bool p1, address p2, bool p3) internal pure {
11544
        bytes32 m0;
11545
        bytes32 m1;
11546
        bytes32 m2;
11547
        bytes32 m3;
11548
        bytes32 m4;
11549
        bytes32 m5;
11550
        bytes32 m6;
11551
        /// @solidity memory-safe-assembly
11552
        assembly {
11553
            function writeString(pos, w) {
11554
                let length := 0
11555
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11556
                mstore(pos, length)
11557
                let shift := sub(256, shl(3, length))
11558
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11559
            }
11560
            m0 := mload(0x00)
11561
            m1 := mload(0x20)
11562
            m2 := mload(0x40)
11563
            m3 := mload(0x60)
11564
            m4 := mload(0x80)
11565
            m5 := mload(0xa0)
11566
            m6 := mload(0xc0)
11567
            // Selector of `log(string,bool,address,bool)`.
11568
            mstore(0x00, 0x958c28c6)
11569
            mstore(0x20, 0x80)
11570
            mstore(0x40, p1)
11571
            mstore(0x60, p2)
11572
            mstore(0x80, p3)
11573
            writeString(0xa0, p0)
11574
        }
11575
        _sendLogPayload(0x1c, 0xc4);
11576
        /// @solidity memory-safe-assembly
11577
        assembly {
11578
            mstore(0x00, m0)
11579
            mstore(0x20, m1)
11580
            mstore(0x40, m2)
11581
            mstore(0x60, m3)
11582
            mstore(0x80, m4)
11583
            mstore(0xa0, m5)
11584
            mstore(0xc0, m6)
11585
        }
11586
    }
11587

                            
                        
11588
    function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure {
11589
        bytes32 m0;
11590
        bytes32 m1;
11591
        bytes32 m2;
11592
        bytes32 m3;
11593
        bytes32 m4;
11594
        bytes32 m5;
11595
        bytes32 m6;
11596
        /// @solidity memory-safe-assembly
11597
        assembly {
11598
            function writeString(pos, w) {
11599
                let length := 0
11600
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11601
                mstore(pos, length)
11602
                let shift := sub(256, shl(3, length))
11603
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11604
            }
11605
            m0 := mload(0x00)
11606
            m1 := mload(0x20)
11607
            m2 := mload(0x40)
11608
            m3 := mload(0x60)
11609
            m4 := mload(0x80)
11610
            m5 := mload(0xa0)
11611
            m6 := mload(0xc0)
11612
            // Selector of `log(string,bool,address,uint256)`.
11613
            mstore(0x00, 0x5d08bb05)
11614
            mstore(0x20, 0x80)
11615
            mstore(0x40, p1)
11616
            mstore(0x60, p2)
11617
            mstore(0x80, p3)
11618
            writeString(0xa0, p0)
11619
        }
11620
        _sendLogPayload(0x1c, 0xc4);
11621
        /// @solidity memory-safe-assembly
11622
        assembly {
11623
            mstore(0x00, m0)
11624
            mstore(0x20, m1)
11625
            mstore(0x40, m2)
11626
            mstore(0x60, m3)
11627
            mstore(0x80, m4)
11628
            mstore(0xa0, m5)
11629
            mstore(0xc0, m6)
11630
        }
11631
    }
11632

                            
                        
11633
    function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure {
11634
        bytes32 m0;
11635
        bytes32 m1;
11636
        bytes32 m2;
11637
        bytes32 m3;
11638
        bytes32 m4;
11639
        bytes32 m5;
11640
        bytes32 m6;
11641
        bytes32 m7;
11642
        bytes32 m8;
11643
        /// @solidity memory-safe-assembly
11644
        assembly {
11645
            function writeString(pos, w) {
11646
                let length := 0
11647
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11648
                mstore(pos, length)
11649
                let shift := sub(256, shl(3, length))
11650
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11651
            }
11652
            m0 := mload(0x00)
11653
            m1 := mload(0x20)
11654
            m2 := mload(0x40)
11655
            m3 := mload(0x60)
11656
            m4 := mload(0x80)
11657
            m5 := mload(0xa0)
11658
            m6 := mload(0xc0)
11659
            m7 := mload(0xe0)
11660
            m8 := mload(0x100)
11661
            // Selector of `log(string,bool,address,string)`.
11662
            mstore(0x00, 0x2d8e33a4)
11663
            mstore(0x20, 0x80)
11664
            mstore(0x40, p1)
11665
            mstore(0x60, p2)
11666
            mstore(0x80, 0xc0)
11667
            writeString(0xa0, p0)
11668
            writeString(0xe0, p3)
11669
        }
11670
        _sendLogPayload(0x1c, 0x104);
11671
        /// @solidity memory-safe-assembly
11672
        assembly {
11673
            mstore(0x00, m0)
11674
            mstore(0x20, m1)
11675
            mstore(0x40, m2)
11676
            mstore(0x60, m3)
11677
            mstore(0x80, m4)
11678
            mstore(0xa0, m5)
11679
            mstore(0xc0, m6)
11680
            mstore(0xe0, m7)
11681
            mstore(0x100, m8)
11682
        }
11683
    }
11684

                            
                        
11685
    function log(bytes32 p0, bool p1, bool p2, address p3) internal pure {
11686
        bytes32 m0;
11687
        bytes32 m1;
11688
        bytes32 m2;
11689
        bytes32 m3;
11690
        bytes32 m4;
11691
        bytes32 m5;
11692
        bytes32 m6;
11693
        /// @solidity memory-safe-assembly
11694
        assembly {
11695
            function writeString(pos, w) {
11696
                let length := 0
11697
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11698
                mstore(pos, length)
11699
                let shift := sub(256, shl(3, length))
11700
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11701
            }
11702
            m0 := mload(0x00)
11703
            m1 := mload(0x20)
11704
            m2 := mload(0x40)
11705
            m3 := mload(0x60)
11706
            m4 := mload(0x80)
11707
            m5 := mload(0xa0)
11708
            m6 := mload(0xc0)
11709
            // Selector of `log(string,bool,bool,address)`.
11710
            mstore(0x00, 0x7190a529)
11711
            mstore(0x20, 0x80)
11712
            mstore(0x40, p1)
11713
            mstore(0x60, p2)
11714
            mstore(0x80, p3)
11715
            writeString(0xa0, p0)
11716
        }
11717
        _sendLogPayload(0x1c, 0xc4);
11718
        /// @solidity memory-safe-assembly
11719
        assembly {
11720
            mstore(0x00, m0)
11721
            mstore(0x20, m1)
11722
            mstore(0x40, m2)
11723
            mstore(0x60, m3)
11724
            mstore(0x80, m4)
11725
            mstore(0xa0, m5)
11726
            mstore(0xc0, m6)
11727
        }
11728
    }
11729

                            
                        
11730
    function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure {
11731
        bytes32 m0;
11732
        bytes32 m1;
11733
        bytes32 m2;
11734
        bytes32 m3;
11735
        bytes32 m4;
11736
        bytes32 m5;
11737
        bytes32 m6;
11738
        /// @solidity memory-safe-assembly
11739
        assembly {
11740
            function writeString(pos, w) {
11741
                let length := 0
11742
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11743
                mstore(pos, length)
11744
                let shift := sub(256, shl(3, length))
11745
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11746
            }
11747
            m0 := mload(0x00)
11748
            m1 := mload(0x20)
11749
            m2 := mload(0x40)
11750
            m3 := mload(0x60)
11751
            m4 := mload(0x80)
11752
            m5 := mload(0xa0)
11753
            m6 := mload(0xc0)
11754
            // Selector of `log(string,bool,bool,bool)`.
11755
            mstore(0x00, 0x895af8c5)
11756
            mstore(0x20, 0x80)
11757
            mstore(0x40, p1)
11758
            mstore(0x60, p2)
11759
            mstore(0x80, p3)
11760
            writeString(0xa0, p0)
11761
        }
11762
        _sendLogPayload(0x1c, 0xc4);
11763
        /// @solidity memory-safe-assembly
11764
        assembly {
11765
            mstore(0x00, m0)
11766
            mstore(0x20, m1)
11767
            mstore(0x40, m2)
11768
            mstore(0x60, m3)
11769
            mstore(0x80, m4)
11770
            mstore(0xa0, m5)
11771
            mstore(0xc0, m6)
11772
        }
11773
    }
11774

                            
                        
11775
    function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure {
11776
        bytes32 m0;
11777
        bytes32 m1;
11778
        bytes32 m2;
11779
        bytes32 m3;
11780
        bytes32 m4;
11781
        bytes32 m5;
11782
        bytes32 m6;
11783
        /// @solidity memory-safe-assembly
11784
        assembly {
11785
            function writeString(pos, w) {
11786
                let length := 0
11787
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11788
                mstore(pos, length)
11789
                let shift := sub(256, shl(3, length))
11790
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11791
            }
11792
            m0 := mload(0x00)
11793
            m1 := mload(0x20)
11794
            m2 := mload(0x40)
11795
            m3 := mload(0x60)
11796
            m4 := mload(0x80)
11797
            m5 := mload(0xa0)
11798
            m6 := mload(0xc0)
11799
            // Selector of `log(string,bool,bool,uint256)`.
11800
            mstore(0x00, 0x8e3f78a9)
11801
            mstore(0x20, 0x80)
11802
            mstore(0x40, p1)
11803
            mstore(0x60, p2)
11804
            mstore(0x80, p3)
11805
            writeString(0xa0, p0)
11806
        }
11807
        _sendLogPayload(0x1c, 0xc4);
11808
        /// @solidity memory-safe-assembly
11809
        assembly {
11810
            mstore(0x00, m0)
11811
            mstore(0x20, m1)
11812
            mstore(0x40, m2)
11813
            mstore(0x60, m3)
11814
            mstore(0x80, m4)
11815
            mstore(0xa0, m5)
11816
            mstore(0xc0, m6)
11817
        }
11818
    }
11819

                            
                        
11820
    function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure {
11821
        bytes32 m0;
11822
        bytes32 m1;
11823
        bytes32 m2;
11824
        bytes32 m3;
11825
        bytes32 m4;
11826
        bytes32 m5;
11827
        bytes32 m6;
11828
        bytes32 m7;
11829
        bytes32 m8;
11830
        /// @solidity memory-safe-assembly
11831
        assembly {
11832
            function writeString(pos, w) {
11833
                let length := 0
11834
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11835
                mstore(pos, length)
11836
                let shift := sub(256, shl(3, length))
11837
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11838
            }
11839
            m0 := mload(0x00)
11840
            m1 := mload(0x20)
11841
            m2 := mload(0x40)
11842
            m3 := mload(0x60)
11843
            m4 := mload(0x80)
11844
            m5 := mload(0xa0)
11845
            m6 := mload(0xc0)
11846
            m7 := mload(0xe0)
11847
            m8 := mload(0x100)
11848
            // Selector of `log(string,bool,bool,string)`.
11849
            mstore(0x00, 0x9d22d5dd)
11850
            mstore(0x20, 0x80)
11851
            mstore(0x40, p1)
11852
            mstore(0x60, p2)
11853
            mstore(0x80, 0xc0)
11854
            writeString(0xa0, p0)
11855
            writeString(0xe0, p3)
11856
        }
11857
        _sendLogPayload(0x1c, 0x104);
11858
        /// @solidity memory-safe-assembly
11859
        assembly {
11860
            mstore(0x00, m0)
11861
            mstore(0x20, m1)
11862
            mstore(0x40, m2)
11863
            mstore(0x60, m3)
11864
            mstore(0x80, m4)
11865
            mstore(0xa0, m5)
11866
            mstore(0xc0, m6)
11867
            mstore(0xe0, m7)
11868
            mstore(0x100, m8)
11869
        }
11870
    }
11871

                            
                        
11872
    function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure {
11873
        bytes32 m0;
11874
        bytes32 m1;
11875
        bytes32 m2;
11876
        bytes32 m3;
11877
        bytes32 m4;
11878
        bytes32 m5;
11879
        bytes32 m6;
11880
        /// @solidity memory-safe-assembly
11881
        assembly {
11882
            function writeString(pos, w) {
11883
                let length := 0
11884
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11885
                mstore(pos, length)
11886
                let shift := sub(256, shl(3, length))
11887
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11888
            }
11889
            m0 := mload(0x00)
11890
            m1 := mload(0x20)
11891
            m2 := mload(0x40)
11892
            m3 := mload(0x60)
11893
            m4 := mload(0x80)
11894
            m5 := mload(0xa0)
11895
            m6 := mload(0xc0)
11896
            // Selector of `log(string,bool,uint256,address)`.
11897
            mstore(0x00, 0x935e09bf)
11898
            mstore(0x20, 0x80)
11899
            mstore(0x40, p1)
11900
            mstore(0x60, p2)
11901
            mstore(0x80, p3)
11902
            writeString(0xa0, p0)
11903
        }
11904
        _sendLogPayload(0x1c, 0xc4);
11905
        /// @solidity memory-safe-assembly
11906
        assembly {
11907
            mstore(0x00, m0)
11908
            mstore(0x20, m1)
11909
            mstore(0x40, m2)
11910
            mstore(0x60, m3)
11911
            mstore(0x80, m4)
11912
            mstore(0xa0, m5)
11913
            mstore(0xc0, m6)
11914
        }
11915
    }
11916

                            
                        
11917
    function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure {
11918
        bytes32 m0;
11919
        bytes32 m1;
11920
        bytes32 m2;
11921
        bytes32 m3;
11922
        bytes32 m4;
11923
        bytes32 m5;
11924
        bytes32 m6;
11925
        /// @solidity memory-safe-assembly
11926
        assembly {
11927
            function writeString(pos, w) {
11928
                let length := 0
11929
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11930
                mstore(pos, length)
11931
                let shift := sub(256, shl(3, length))
11932
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11933
            }
11934
            m0 := mload(0x00)
11935
            m1 := mload(0x20)
11936
            m2 := mload(0x40)
11937
            m3 := mload(0x60)
11938
            m4 := mload(0x80)
11939
            m5 := mload(0xa0)
11940
            m6 := mload(0xc0)
11941
            // Selector of `log(string,bool,uint256,bool)`.
11942
            mstore(0x00, 0x8af7cf8a)
11943
            mstore(0x20, 0x80)
11944
            mstore(0x40, p1)
11945
            mstore(0x60, p2)
11946
            mstore(0x80, p3)
11947
            writeString(0xa0, p0)
11948
        }
11949
        _sendLogPayload(0x1c, 0xc4);
11950
        /// @solidity memory-safe-assembly
11951
        assembly {
11952
            mstore(0x00, m0)
11953
            mstore(0x20, m1)
11954
            mstore(0x40, m2)
11955
            mstore(0x60, m3)
11956
            mstore(0x80, m4)
11957
            mstore(0xa0, m5)
11958
            mstore(0xc0, m6)
11959
        }
11960
    }
11961

                            
                        
11962
    function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure {
11963
        bytes32 m0;
11964
        bytes32 m1;
11965
        bytes32 m2;
11966
        bytes32 m3;
11967
        bytes32 m4;
11968
        bytes32 m5;
11969
        bytes32 m6;
11970
        /// @solidity memory-safe-assembly
11971
        assembly {
11972
            function writeString(pos, w) {
11973
                let length := 0
11974
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
11975
                mstore(pos, length)
11976
                let shift := sub(256, shl(3, length))
11977
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
11978
            }
11979
            m0 := mload(0x00)
11980
            m1 := mload(0x20)
11981
            m2 := mload(0x40)
11982
            m3 := mload(0x60)
11983
            m4 := mload(0x80)
11984
            m5 := mload(0xa0)
11985
            m6 := mload(0xc0)
11986
            // Selector of `log(string,bool,uint256,uint256)`.
11987
            mstore(0x00, 0x64b5bb67)
11988
            mstore(0x20, 0x80)
11989
            mstore(0x40, p1)
11990
            mstore(0x60, p2)
11991
            mstore(0x80, p3)
11992
            writeString(0xa0, p0)
11993
        }
11994
        _sendLogPayload(0x1c, 0xc4);
11995
        /// @solidity memory-safe-assembly
11996
        assembly {
11997
            mstore(0x00, m0)
11998
            mstore(0x20, m1)
11999
            mstore(0x40, m2)
12000
            mstore(0x60, m3)
12001
            mstore(0x80, m4)
12002
            mstore(0xa0, m5)
12003
            mstore(0xc0, m6)
12004
        }
12005
    }
12006

                            
                        
12007
    function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
12008
        bytes32 m0;
12009
        bytes32 m1;
12010
        bytes32 m2;
12011
        bytes32 m3;
12012
        bytes32 m4;
12013
        bytes32 m5;
12014
        bytes32 m6;
12015
        bytes32 m7;
12016
        bytes32 m8;
12017
        /// @solidity memory-safe-assembly
12018
        assembly {
12019
            function writeString(pos, w) {
12020
                let length := 0
12021
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12022
                mstore(pos, length)
12023
                let shift := sub(256, shl(3, length))
12024
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12025
            }
12026
            m0 := mload(0x00)
12027
            m1 := mload(0x20)
12028
            m2 := mload(0x40)
12029
            m3 := mload(0x60)
12030
            m4 := mload(0x80)
12031
            m5 := mload(0xa0)
12032
            m6 := mload(0xc0)
12033
            m7 := mload(0xe0)
12034
            m8 := mload(0x100)
12035
            // Selector of `log(string,bool,uint256,string)`.
12036
            mstore(0x00, 0x742d6ee7)
12037
            mstore(0x20, 0x80)
12038
            mstore(0x40, p1)
12039
            mstore(0x60, p2)
12040
            mstore(0x80, 0xc0)
12041
            writeString(0xa0, p0)
12042
            writeString(0xe0, p3)
12043
        }
12044
        _sendLogPayload(0x1c, 0x104);
12045
        /// @solidity memory-safe-assembly
12046
        assembly {
12047
            mstore(0x00, m0)
12048
            mstore(0x20, m1)
12049
            mstore(0x40, m2)
12050
            mstore(0x60, m3)
12051
            mstore(0x80, m4)
12052
            mstore(0xa0, m5)
12053
            mstore(0xc0, m6)
12054
            mstore(0xe0, m7)
12055
            mstore(0x100, m8)
12056
        }
12057
    }
12058

                            
                        
12059
    function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure {
12060
        bytes32 m0;
12061
        bytes32 m1;
12062
        bytes32 m2;
12063
        bytes32 m3;
12064
        bytes32 m4;
12065
        bytes32 m5;
12066
        bytes32 m6;
12067
        bytes32 m7;
12068
        bytes32 m8;
12069
        /// @solidity memory-safe-assembly
12070
        assembly {
12071
            function writeString(pos, w) {
12072
                let length := 0
12073
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12074
                mstore(pos, length)
12075
                let shift := sub(256, shl(3, length))
12076
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12077
            }
12078
            m0 := mload(0x00)
12079
            m1 := mload(0x20)
12080
            m2 := mload(0x40)
12081
            m3 := mload(0x60)
12082
            m4 := mload(0x80)
12083
            m5 := mload(0xa0)
12084
            m6 := mload(0xc0)
12085
            m7 := mload(0xe0)
12086
            m8 := mload(0x100)
12087
            // Selector of `log(string,bool,string,address)`.
12088
            mstore(0x00, 0xe0625b29)
12089
            mstore(0x20, 0x80)
12090
            mstore(0x40, p1)
12091
            mstore(0x60, 0xc0)
12092
            mstore(0x80, p3)
12093
            writeString(0xa0, p0)
12094
            writeString(0xe0, p2)
12095
        }
12096
        _sendLogPayload(0x1c, 0x104);
12097
        /// @solidity memory-safe-assembly
12098
        assembly {
12099
            mstore(0x00, m0)
12100
            mstore(0x20, m1)
12101
            mstore(0x40, m2)
12102
            mstore(0x60, m3)
12103
            mstore(0x80, m4)
12104
            mstore(0xa0, m5)
12105
            mstore(0xc0, m6)
12106
            mstore(0xe0, m7)
12107
            mstore(0x100, m8)
12108
        }
12109
    }
12110

                            
                        
12111
    function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure {
12112
        bytes32 m0;
12113
        bytes32 m1;
12114
        bytes32 m2;
12115
        bytes32 m3;
12116
        bytes32 m4;
12117
        bytes32 m5;
12118
        bytes32 m6;
12119
        bytes32 m7;
12120
        bytes32 m8;
12121
        /// @solidity memory-safe-assembly
12122
        assembly {
12123
            function writeString(pos, w) {
12124
                let length := 0
12125
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12126
                mstore(pos, length)
12127
                let shift := sub(256, shl(3, length))
12128
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12129
            }
12130
            m0 := mload(0x00)
12131
            m1 := mload(0x20)
12132
            m2 := mload(0x40)
12133
            m3 := mload(0x60)
12134
            m4 := mload(0x80)
12135
            m5 := mload(0xa0)
12136
            m6 := mload(0xc0)
12137
            m7 := mload(0xe0)
12138
            m8 := mload(0x100)
12139
            // Selector of `log(string,bool,string,bool)`.
12140
            mstore(0x00, 0x3f8a701d)
12141
            mstore(0x20, 0x80)
12142
            mstore(0x40, p1)
12143
            mstore(0x60, 0xc0)
12144
            mstore(0x80, p3)
12145
            writeString(0xa0, p0)
12146
            writeString(0xe0, p2)
12147
        }
12148
        _sendLogPayload(0x1c, 0x104);
12149
        /// @solidity memory-safe-assembly
12150
        assembly {
12151
            mstore(0x00, m0)
12152
            mstore(0x20, m1)
12153
            mstore(0x40, m2)
12154
            mstore(0x60, m3)
12155
            mstore(0x80, m4)
12156
            mstore(0xa0, m5)
12157
            mstore(0xc0, m6)
12158
            mstore(0xe0, m7)
12159
            mstore(0x100, m8)
12160
        }
12161
    }
12162

                            
                        
12163
    function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
12164
        bytes32 m0;
12165
        bytes32 m1;
12166
        bytes32 m2;
12167
        bytes32 m3;
12168
        bytes32 m4;
12169
        bytes32 m5;
12170
        bytes32 m6;
12171
        bytes32 m7;
12172
        bytes32 m8;
12173
        /// @solidity memory-safe-assembly
12174
        assembly {
12175
            function writeString(pos, w) {
12176
                let length := 0
12177
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12178
                mstore(pos, length)
12179
                let shift := sub(256, shl(3, length))
12180
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12181
            }
12182
            m0 := mload(0x00)
12183
            m1 := mload(0x20)
12184
            m2 := mload(0x40)
12185
            m3 := mload(0x60)
12186
            m4 := mload(0x80)
12187
            m5 := mload(0xa0)
12188
            m6 := mload(0xc0)
12189
            m7 := mload(0xe0)
12190
            m8 := mload(0x100)
12191
            // Selector of `log(string,bool,string,uint256)`.
12192
            mstore(0x00, 0x24f91465)
12193
            mstore(0x20, 0x80)
12194
            mstore(0x40, p1)
12195
            mstore(0x60, 0xc0)
12196
            mstore(0x80, p3)
12197
            writeString(0xa0, p0)
12198
            writeString(0xe0, p2)
12199
        }
12200
        _sendLogPayload(0x1c, 0x104);
12201
        /// @solidity memory-safe-assembly
12202
        assembly {
12203
            mstore(0x00, m0)
12204
            mstore(0x20, m1)
12205
            mstore(0x40, m2)
12206
            mstore(0x60, m3)
12207
            mstore(0x80, m4)
12208
            mstore(0xa0, m5)
12209
            mstore(0xc0, m6)
12210
            mstore(0xe0, m7)
12211
            mstore(0x100, m8)
12212
        }
12213
    }
12214

                            
                        
12215
    function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
12216
        bytes32 m0;
12217
        bytes32 m1;
12218
        bytes32 m2;
12219
        bytes32 m3;
12220
        bytes32 m4;
12221
        bytes32 m5;
12222
        bytes32 m6;
12223
        bytes32 m7;
12224
        bytes32 m8;
12225
        bytes32 m9;
12226
        bytes32 m10;
12227
        /// @solidity memory-safe-assembly
12228
        assembly {
12229
            function writeString(pos, w) {
12230
                let length := 0
12231
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12232
                mstore(pos, length)
12233
                let shift := sub(256, shl(3, length))
12234
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12235
            }
12236
            m0 := mload(0x00)
12237
            m1 := mload(0x20)
12238
            m2 := mload(0x40)
12239
            m3 := mload(0x60)
12240
            m4 := mload(0x80)
12241
            m5 := mload(0xa0)
12242
            m6 := mload(0xc0)
12243
            m7 := mload(0xe0)
12244
            m8 := mload(0x100)
12245
            m9 := mload(0x120)
12246
            m10 := mload(0x140)
12247
            // Selector of `log(string,bool,string,string)`.
12248
            mstore(0x00, 0xa826caeb)
12249
            mstore(0x20, 0x80)
12250
            mstore(0x40, p1)
12251
            mstore(0x60, 0xc0)
12252
            mstore(0x80, 0x100)
12253
            writeString(0xa0, p0)
12254
            writeString(0xe0, p2)
12255
            writeString(0x120, p3)
12256
        }
12257
        _sendLogPayload(0x1c, 0x144);
12258
        /// @solidity memory-safe-assembly
12259
        assembly {
12260
            mstore(0x00, m0)
12261
            mstore(0x20, m1)
12262
            mstore(0x40, m2)
12263
            mstore(0x60, m3)
12264
            mstore(0x80, m4)
12265
            mstore(0xa0, m5)
12266
            mstore(0xc0, m6)
12267
            mstore(0xe0, m7)
12268
            mstore(0x100, m8)
12269
            mstore(0x120, m9)
12270
            mstore(0x140, m10)
12271
        }
12272
    }
12273

                            
                        
12274
    function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure {
12275
        bytes32 m0;
12276
        bytes32 m1;
12277
        bytes32 m2;
12278
        bytes32 m3;
12279
        bytes32 m4;
12280
        bytes32 m5;
12281
        bytes32 m6;
12282
        /// @solidity memory-safe-assembly
12283
        assembly {
12284
            function writeString(pos, w) {
12285
                let length := 0
12286
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12287
                mstore(pos, length)
12288
                let shift := sub(256, shl(3, length))
12289
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12290
            }
12291
            m0 := mload(0x00)
12292
            m1 := mload(0x20)
12293
            m2 := mload(0x40)
12294
            m3 := mload(0x60)
12295
            m4 := mload(0x80)
12296
            m5 := mload(0xa0)
12297
            m6 := mload(0xc0)
12298
            // Selector of `log(string,uint256,address,address)`.
12299
            mstore(0x00, 0x5ea2b7ae)
12300
            mstore(0x20, 0x80)
12301
            mstore(0x40, p1)
12302
            mstore(0x60, p2)
12303
            mstore(0x80, p3)
12304
            writeString(0xa0, p0)
12305
        }
12306
        _sendLogPayload(0x1c, 0xc4);
12307
        /// @solidity memory-safe-assembly
12308
        assembly {
12309
            mstore(0x00, m0)
12310
            mstore(0x20, m1)
12311
            mstore(0x40, m2)
12312
            mstore(0x60, m3)
12313
            mstore(0x80, m4)
12314
            mstore(0xa0, m5)
12315
            mstore(0xc0, m6)
12316
        }
12317
    }
12318

                            
                        
12319
    function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure {
12320
        bytes32 m0;
12321
        bytes32 m1;
12322
        bytes32 m2;
12323
        bytes32 m3;
12324
        bytes32 m4;
12325
        bytes32 m5;
12326
        bytes32 m6;
12327
        /// @solidity memory-safe-assembly
12328
        assembly {
12329
            function writeString(pos, w) {
12330
                let length := 0
12331
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12332
                mstore(pos, length)
12333
                let shift := sub(256, shl(3, length))
12334
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12335
            }
12336
            m0 := mload(0x00)
12337
            m1 := mload(0x20)
12338
            m2 := mload(0x40)
12339
            m3 := mload(0x60)
12340
            m4 := mload(0x80)
12341
            m5 := mload(0xa0)
12342
            m6 := mload(0xc0)
12343
            // Selector of `log(string,uint256,address,bool)`.
12344
            mstore(0x00, 0x82112a42)
12345
            mstore(0x20, 0x80)
12346
            mstore(0x40, p1)
12347
            mstore(0x60, p2)
12348
            mstore(0x80, p3)
12349
            writeString(0xa0, p0)
12350
        }
12351
        _sendLogPayload(0x1c, 0xc4);
12352
        /// @solidity memory-safe-assembly
12353
        assembly {
12354
            mstore(0x00, m0)
12355
            mstore(0x20, m1)
12356
            mstore(0x40, m2)
12357
            mstore(0x60, m3)
12358
            mstore(0x80, m4)
12359
            mstore(0xa0, m5)
12360
            mstore(0xc0, m6)
12361
        }
12362
    }
12363

                            
                        
12364
    function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure {
12365
        bytes32 m0;
12366
        bytes32 m1;
12367
        bytes32 m2;
12368
        bytes32 m3;
12369
        bytes32 m4;
12370
        bytes32 m5;
12371
        bytes32 m6;
12372
        /// @solidity memory-safe-assembly
12373
        assembly {
12374
            function writeString(pos, w) {
12375
                let length := 0
12376
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12377
                mstore(pos, length)
12378
                let shift := sub(256, shl(3, length))
12379
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12380
            }
12381
            m0 := mload(0x00)
12382
            m1 := mload(0x20)
12383
            m2 := mload(0x40)
12384
            m3 := mload(0x60)
12385
            m4 := mload(0x80)
12386
            m5 := mload(0xa0)
12387
            m6 := mload(0xc0)
12388
            // Selector of `log(string,uint256,address,uint256)`.
12389
            mstore(0x00, 0x4f04fdc6)
12390
            mstore(0x20, 0x80)
12391
            mstore(0x40, p1)
12392
            mstore(0x60, p2)
12393
            mstore(0x80, p3)
12394
            writeString(0xa0, p0)
12395
        }
12396
        _sendLogPayload(0x1c, 0xc4);
12397
        /// @solidity memory-safe-assembly
12398
        assembly {
12399
            mstore(0x00, m0)
12400
            mstore(0x20, m1)
12401
            mstore(0x40, m2)
12402
            mstore(0x60, m3)
12403
            mstore(0x80, m4)
12404
            mstore(0xa0, m5)
12405
            mstore(0xc0, m6)
12406
        }
12407
    }
12408

                            
                        
12409
    function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure {
12410
        bytes32 m0;
12411
        bytes32 m1;
12412
        bytes32 m2;
12413
        bytes32 m3;
12414
        bytes32 m4;
12415
        bytes32 m5;
12416
        bytes32 m6;
12417
        bytes32 m7;
12418
        bytes32 m8;
12419
        /// @solidity memory-safe-assembly
12420
        assembly {
12421
            function writeString(pos, w) {
12422
                let length := 0
12423
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12424
                mstore(pos, length)
12425
                let shift := sub(256, shl(3, length))
12426
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12427
            }
12428
            m0 := mload(0x00)
12429
            m1 := mload(0x20)
12430
            m2 := mload(0x40)
12431
            m3 := mload(0x60)
12432
            m4 := mload(0x80)
12433
            m5 := mload(0xa0)
12434
            m6 := mload(0xc0)
12435
            m7 := mload(0xe0)
12436
            m8 := mload(0x100)
12437
            // Selector of `log(string,uint256,address,string)`.
12438
            mstore(0x00, 0x9ffb2f93)
12439
            mstore(0x20, 0x80)
12440
            mstore(0x40, p1)
12441
            mstore(0x60, p2)
12442
            mstore(0x80, 0xc0)
12443
            writeString(0xa0, p0)
12444
            writeString(0xe0, p3)
12445
        }
12446
        _sendLogPayload(0x1c, 0x104);
12447
        /// @solidity memory-safe-assembly
12448
        assembly {
12449
            mstore(0x00, m0)
12450
            mstore(0x20, m1)
12451
            mstore(0x40, m2)
12452
            mstore(0x60, m3)
12453
            mstore(0x80, m4)
12454
            mstore(0xa0, m5)
12455
            mstore(0xc0, m6)
12456
            mstore(0xe0, m7)
12457
            mstore(0x100, m8)
12458
        }
12459
    }
12460

                            
                        
12461
    function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure {
12462
        bytes32 m0;
12463
        bytes32 m1;
12464
        bytes32 m2;
12465
        bytes32 m3;
12466
        bytes32 m4;
12467
        bytes32 m5;
12468
        bytes32 m6;
12469
        /// @solidity memory-safe-assembly
12470
        assembly {
12471
            function writeString(pos, w) {
12472
                let length := 0
12473
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12474
                mstore(pos, length)
12475
                let shift := sub(256, shl(3, length))
12476
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12477
            }
12478
            m0 := mload(0x00)
12479
            m1 := mload(0x20)
12480
            m2 := mload(0x40)
12481
            m3 := mload(0x60)
12482
            m4 := mload(0x80)
12483
            m5 := mload(0xa0)
12484
            m6 := mload(0xc0)
12485
            // Selector of `log(string,uint256,bool,address)`.
12486
            mstore(0x00, 0xe0e95b98)
12487
            mstore(0x20, 0x80)
12488
            mstore(0x40, p1)
12489
            mstore(0x60, p2)
12490
            mstore(0x80, p3)
12491
            writeString(0xa0, p0)
12492
        }
12493
        _sendLogPayload(0x1c, 0xc4);
12494
        /// @solidity memory-safe-assembly
12495
        assembly {
12496
            mstore(0x00, m0)
12497
            mstore(0x20, m1)
12498
            mstore(0x40, m2)
12499
            mstore(0x60, m3)
12500
            mstore(0x80, m4)
12501
            mstore(0xa0, m5)
12502
            mstore(0xc0, m6)
12503
        }
12504
    }
12505

                            
                        
12506
    function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure {
12507
        bytes32 m0;
12508
        bytes32 m1;
12509
        bytes32 m2;
12510
        bytes32 m3;
12511
        bytes32 m4;
12512
        bytes32 m5;
12513
        bytes32 m6;
12514
        /// @solidity memory-safe-assembly
12515
        assembly {
12516
            function writeString(pos, w) {
12517
                let length := 0
12518
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12519
                mstore(pos, length)
12520
                let shift := sub(256, shl(3, length))
12521
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12522
            }
12523
            m0 := mload(0x00)
12524
            m1 := mload(0x20)
12525
            m2 := mload(0x40)
12526
            m3 := mload(0x60)
12527
            m4 := mload(0x80)
12528
            m5 := mload(0xa0)
12529
            m6 := mload(0xc0)
12530
            // Selector of `log(string,uint256,bool,bool)`.
12531
            mstore(0x00, 0x354c36d6)
12532
            mstore(0x20, 0x80)
12533
            mstore(0x40, p1)
12534
            mstore(0x60, p2)
12535
            mstore(0x80, p3)
12536
            writeString(0xa0, p0)
12537
        }
12538
        _sendLogPayload(0x1c, 0xc4);
12539
        /// @solidity memory-safe-assembly
12540
        assembly {
12541
            mstore(0x00, m0)
12542
            mstore(0x20, m1)
12543
            mstore(0x40, m2)
12544
            mstore(0x60, m3)
12545
            mstore(0x80, m4)
12546
            mstore(0xa0, m5)
12547
            mstore(0xc0, m6)
12548
        }
12549
    }
12550

                            
                        
12551
    function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure {
12552
        bytes32 m0;
12553
        bytes32 m1;
12554
        bytes32 m2;
12555
        bytes32 m3;
12556
        bytes32 m4;
12557
        bytes32 m5;
12558
        bytes32 m6;
12559
        /// @solidity memory-safe-assembly
12560
        assembly {
12561
            function writeString(pos, w) {
12562
                let length := 0
12563
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12564
                mstore(pos, length)
12565
                let shift := sub(256, shl(3, length))
12566
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12567
            }
12568
            m0 := mload(0x00)
12569
            m1 := mload(0x20)
12570
            m2 := mload(0x40)
12571
            m3 := mload(0x60)
12572
            m4 := mload(0x80)
12573
            m5 := mload(0xa0)
12574
            m6 := mload(0xc0)
12575
            // Selector of `log(string,uint256,bool,uint256)`.
12576
            mstore(0x00, 0xe41b6f6f)
12577
            mstore(0x20, 0x80)
12578
            mstore(0x40, p1)
12579
            mstore(0x60, p2)
12580
            mstore(0x80, p3)
12581
            writeString(0xa0, p0)
12582
        }
12583
        _sendLogPayload(0x1c, 0xc4);
12584
        /// @solidity memory-safe-assembly
12585
        assembly {
12586
            mstore(0x00, m0)
12587
            mstore(0x20, m1)
12588
            mstore(0x40, m2)
12589
            mstore(0x60, m3)
12590
            mstore(0x80, m4)
12591
            mstore(0xa0, m5)
12592
            mstore(0xc0, m6)
12593
        }
12594
    }
12595

                            
                        
12596
    function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
12597
        bytes32 m0;
12598
        bytes32 m1;
12599
        bytes32 m2;
12600
        bytes32 m3;
12601
        bytes32 m4;
12602
        bytes32 m5;
12603
        bytes32 m6;
12604
        bytes32 m7;
12605
        bytes32 m8;
12606
        /// @solidity memory-safe-assembly
12607
        assembly {
12608
            function writeString(pos, w) {
12609
                let length := 0
12610
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12611
                mstore(pos, length)
12612
                let shift := sub(256, shl(3, length))
12613
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12614
            }
12615
            m0 := mload(0x00)
12616
            m1 := mload(0x20)
12617
            m2 := mload(0x40)
12618
            m3 := mload(0x60)
12619
            m4 := mload(0x80)
12620
            m5 := mload(0xa0)
12621
            m6 := mload(0xc0)
12622
            m7 := mload(0xe0)
12623
            m8 := mload(0x100)
12624
            // Selector of `log(string,uint256,bool,string)`.
12625
            mstore(0x00, 0xabf73a98)
12626
            mstore(0x20, 0x80)
12627
            mstore(0x40, p1)
12628
            mstore(0x60, p2)
12629
            mstore(0x80, 0xc0)
12630
            writeString(0xa0, p0)
12631
            writeString(0xe0, p3)
12632
        }
12633
        _sendLogPayload(0x1c, 0x104);
12634
        /// @solidity memory-safe-assembly
12635
        assembly {
12636
            mstore(0x00, m0)
12637
            mstore(0x20, m1)
12638
            mstore(0x40, m2)
12639
            mstore(0x60, m3)
12640
            mstore(0x80, m4)
12641
            mstore(0xa0, m5)
12642
            mstore(0xc0, m6)
12643
            mstore(0xe0, m7)
12644
            mstore(0x100, m8)
12645
        }
12646
    }
12647

                            
                        
12648
    function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure {
12649
        bytes32 m0;
12650
        bytes32 m1;
12651
        bytes32 m2;
12652
        bytes32 m3;
12653
        bytes32 m4;
12654
        bytes32 m5;
12655
        bytes32 m6;
12656
        /// @solidity memory-safe-assembly
12657
        assembly {
12658
            function writeString(pos, w) {
12659
                let length := 0
12660
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12661
                mstore(pos, length)
12662
                let shift := sub(256, shl(3, length))
12663
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12664
            }
12665
            m0 := mload(0x00)
12666
            m1 := mload(0x20)
12667
            m2 := mload(0x40)
12668
            m3 := mload(0x60)
12669
            m4 := mload(0x80)
12670
            m5 := mload(0xa0)
12671
            m6 := mload(0xc0)
12672
            // Selector of `log(string,uint256,uint256,address)`.
12673
            mstore(0x00, 0xe21de278)
12674
            mstore(0x20, 0x80)
12675
            mstore(0x40, p1)
12676
            mstore(0x60, p2)
12677
            mstore(0x80, p3)
12678
            writeString(0xa0, p0)
12679
        }
12680
        _sendLogPayload(0x1c, 0xc4);
12681
        /// @solidity memory-safe-assembly
12682
        assembly {
12683
            mstore(0x00, m0)
12684
            mstore(0x20, m1)
12685
            mstore(0x40, m2)
12686
            mstore(0x60, m3)
12687
            mstore(0x80, m4)
12688
            mstore(0xa0, m5)
12689
            mstore(0xc0, m6)
12690
        }
12691
    }
12692

                            
                        
12693
    function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure {
12694
        bytes32 m0;
12695
        bytes32 m1;
12696
        bytes32 m2;
12697
        bytes32 m3;
12698
        bytes32 m4;
12699
        bytes32 m5;
12700
        bytes32 m6;
12701
        /// @solidity memory-safe-assembly
12702
        assembly {
12703
            function writeString(pos, w) {
12704
                let length := 0
12705
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12706
                mstore(pos, length)
12707
                let shift := sub(256, shl(3, length))
12708
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12709
            }
12710
            m0 := mload(0x00)
12711
            m1 := mload(0x20)
12712
            m2 := mload(0x40)
12713
            m3 := mload(0x60)
12714
            m4 := mload(0x80)
12715
            m5 := mload(0xa0)
12716
            m6 := mload(0xc0)
12717
            // Selector of `log(string,uint256,uint256,bool)`.
12718
            mstore(0x00, 0x7626db92)
12719
            mstore(0x20, 0x80)
12720
            mstore(0x40, p1)
12721
            mstore(0x60, p2)
12722
            mstore(0x80, p3)
12723
            writeString(0xa0, p0)
12724
        }
12725
        _sendLogPayload(0x1c, 0xc4);
12726
        /// @solidity memory-safe-assembly
12727
        assembly {
12728
            mstore(0x00, m0)
12729
            mstore(0x20, m1)
12730
            mstore(0x40, m2)
12731
            mstore(0x60, m3)
12732
            mstore(0x80, m4)
12733
            mstore(0xa0, m5)
12734
            mstore(0xc0, m6)
12735
        }
12736
    }
12737

                            
                        
12738
    function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
12739
        bytes32 m0;
12740
        bytes32 m1;
12741
        bytes32 m2;
12742
        bytes32 m3;
12743
        bytes32 m4;
12744
        bytes32 m5;
12745
        bytes32 m6;
12746
        /// @solidity memory-safe-assembly
12747
        assembly {
12748
            function writeString(pos, w) {
12749
                let length := 0
12750
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12751
                mstore(pos, length)
12752
                let shift := sub(256, shl(3, length))
12753
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12754
            }
12755
            m0 := mload(0x00)
12756
            m1 := mload(0x20)
12757
            m2 := mload(0x40)
12758
            m3 := mload(0x60)
12759
            m4 := mload(0x80)
12760
            m5 := mload(0xa0)
12761
            m6 := mload(0xc0)
12762
            // Selector of `log(string,uint256,uint256,uint256)`.
12763
            mstore(0x00, 0xa7a87853)
12764
            mstore(0x20, 0x80)
12765
            mstore(0x40, p1)
12766
            mstore(0x60, p2)
12767
            mstore(0x80, p3)
12768
            writeString(0xa0, p0)
12769
        }
12770
        _sendLogPayload(0x1c, 0xc4);
12771
        /// @solidity memory-safe-assembly
12772
        assembly {
12773
            mstore(0x00, m0)
12774
            mstore(0x20, m1)
12775
            mstore(0x40, m2)
12776
            mstore(0x60, m3)
12777
            mstore(0x80, m4)
12778
            mstore(0xa0, m5)
12779
            mstore(0xc0, m6)
12780
        }
12781
    }
12782

                            
                        
12783
    function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
12784
        bytes32 m0;
12785
        bytes32 m1;
12786
        bytes32 m2;
12787
        bytes32 m3;
12788
        bytes32 m4;
12789
        bytes32 m5;
12790
        bytes32 m6;
12791
        bytes32 m7;
12792
        bytes32 m8;
12793
        /// @solidity memory-safe-assembly
12794
        assembly {
12795
            function writeString(pos, w) {
12796
                let length := 0
12797
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12798
                mstore(pos, length)
12799
                let shift := sub(256, shl(3, length))
12800
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12801
            }
12802
            m0 := mload(0x00)
12803
            m1 := mload(0x20)
12804
            m2 := mload(0x40)
12805
            m3 := mload(0x60)
12806
            m4 := mload(0x80)
12807
            m5 := mload(0xa0)
12808
            m6 := mload(0xc0)
12809
            m7 := mload(0xe0)
12810
            m8 := mload(0x100)
12811
            // Selector of `log(string,uint256,uint256,string)`.
12812
            mstore(0x00, 0x854b3496)
12813
            mstore(0x20, 0x80)
12814
            mstore(0x40, p1)
12815
            mstore(0x60, p2)
12816
            mstore(0x80, 0xc0)
12817
            writeString(0xa0, p0)
12818
            writeString(0xe0, p3)
12819
        }
12820
        _sendLogPayload(0x1c, 0x104);
12821
        /// @solidity memory-safe-assembly
12822
        assembly {
12823
            mstore(0x00, m0)
12824
            mstore(0x20, m1)
12825
            mstore(0x40, m2)
12826
            mstore(0x60, m3)
12827
            mstore(0x80, m4)
12828
            mstore(0xa0, m5)
12829
            mstore(0xc0, m6)
12830
            mstore(0xe0, m7)
12831
            mstore(0x100, m8)
12832
        }
12833
    }
12834

                            
                        
12835
    function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure {
12836
        bytes32 m0;
12837
        bytes32 m1;
12838
        bytes32 m2;
12839
        bytes32 m3;
12840
        bytes32 m4;
12841
        bytes32 m5;
12842
        bytes32 m6;
12843
        bytes32 m7;
12844
        bytes32 m8;
12845
        /// @solidity memory-safe-assembly
12846
        assembly {
12847
            function writeString(pos, w) {
12848
                let length := 0
12849
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12850
                mstore(pos, length)
12851
                let shift := sub(256, shl(3, length))
12852
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12853
            }
12854
            m0 := mload(0x00)
12855
            m1 := mload(0x20)
12856
            m2 := mload(0x40)
12857
            m3 := mload(0x60)
12858
            m4 := mload(0x80)
12859
            m5 := mload(0xa0)
12860
            m6 := mload(0xc0)
12861
            m7 := mload(0xe0)
12862
            m8 := mload(0x100)
12863
            // Selector of `log(string,uint256,string,address)`.
12864
            mstore(0x00, 0x7c4632a4)
12865
            mstore(0x20, 0x80)
12866
            mstore(0x40, p1)
12867
            mstore(0x60, 0xc0)
12868
            mstore(0x80, p3)
12869
            writeString(0xa0, p0)
12870
            writeString(0xe0, p2)
12871
        }
12872
        _sendLogPayload(0x1c, 0x104);
12873
        /// @solidity memory-safe-assembly
12874
        assembly {
12875
            mstore(0x00, m0)
12876
            mstore(0x20, m1)
12877
            mstore(0x40, m2)
12878
            mstore(0x60, m3)
12879
            mstore(0x80, m4)
12880
            mstore(0xa0, m5)
12881
            mstore(0xc0, m6)
12882
            mstore(0xe0, m7)
12883
            mstore(0x100, m8)
12884
        }
12885
    }
12886

                            
                        
12887
    function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
12888
        bytes32 m0;
12889
        bytes32 m1;
12890
        bytes32 m2;
12891
        bytes32 m3;
12892
        bytes32 m4;
12893
        bytes32 m5;
12894
        bytes32 m6;
12895
        bytes32 m7;
12896
        bytes32 m8;
12897
        /// @solidity memory-safe-assembly
12898
        assembly {
12899
            function writeString(pos, w) {
12900
                let length := 0
12901
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12902
                mstore(pos, length)
12903
                let shift := sub(256, shl(3, length))
12904
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12905
            }
12906
            m0 := mload(0x00)
12907
            m1 := mload(0x20)
12908
            m2 := mload(0x40)
12909
            m3 := mload(0x60)
12910
            m4 := mload(0x80)
12911
            m5 := mload(0xa0)
12912
            m6 := mload(0xc0)
12913
            m7 := mload(0xe0)
12914
            m8 := mload(0x100)
12915
            // Selector of `log(string,uint256,string,bool)`.
12916
            mstore(0x00, 0x7d24491d)
12917
            mstore(0x20, 0x80)
12918
            mstore(0x40, p1)
12919
            mstore(0x60, 0xc0)
12920
            mstore(0x80, p3)
12921
            writeString(0xa0, p0)
12922
            writeString(0xe0, p2)
12923
        }
12924
        _sendLogPayload(0x1c, 0x104);
12925
        /// @solidity memory-safe-assembly
12926
        assembly {
12927
            mstore(0x00, m0)
12928
            mstore(0x20, m1)
12929
            mstore(0x40, m2)
12930
            mstore(0x60, m3)
12931
            mstore(0x80, m4)
12932
            mstore(0xa0, m5)
12933
            mstore(0xc0, m6)
12934
            mstore(0xe0, m7)
12935
            mstore(0x100, m8)
12936
        }
12937
    }
12938

                            
                        
12939
    function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
12940
        bytes32 m0;
12941
        bytes32 m1;
12942
        bytes32 m2;
12943
        bytes32 m3;
12944
        bytes32 m4;
12945
        bytes32 m5;
12946
        bytes32 m6;
12947
        bytes32 m7;
12948
        bytes32 m8;
12949
        /// @solidity memory-safe-assembly
12950
        assembly {
12951
            function writeString(pos, w) {
12952
                let length := 0
12953
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
12954
                mstore(pos, length)
12955
                let shift := sub(256, shl(3, length))
12956
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
12957
            }
12958
            m0 := mload(0x00)
12959
            m1 := mload(0x20)
12960
            m2 := mload(0x40)
12961
            m3 := mload(0x60)
12962
            m4 := mload(0x80)
12963
            m5 := mload(0xa0)
12964
            m6 := mload(0xc0)
12965
            m7 := mload(0xe0)
12966
            m8 := mload(0x100)
12967
            // Selector of `log(string,uint256,string,uint256)`.
12968
            mstore(0x00, 0xc67ea9d1)
12969
            mstore(0x20, 0x80)
12970
            mstore(0x40, p1)
12971
            mstore(0x60, 0xc0)
12972
            mstore(0x80, p3)
12973
            writeString(0xa0, p0)
12974
            writeString(0xe0, p2)
12975
        }
12976
        _sendLogPayload(0x1c, 0x104);
12977
        /// @solidity memory-safe-assembly
12978
        assembly {
12979
            mstore(0x00, m0)
12980
            mstore(0x20, m1)
12981
            mstore(0x40, m2)
12982
            mstore(0x60, m3)
12983
            mstore(0x80, m4)
12984
            mstore(0xa0, m5)
12985
            mstore(0xc0, m6)
12986
            mstore(0xe0, m7)
12987
            mstore(0x100, m8)
12988
        }
12989
    }
12990

                            
                        
12991
    function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
12992
        bytes32 m0;
12993
        bytes32 m1;
12994
        bytes32 m2;
12995
        bytes32 m3;
12996
        bytes32 m4;
12997
        bytes32 m5;
12998
        bytes32 m6;
12999
        bytes32 m7;
13000
        bytes32 m8;
13001
        bytes32 m9;
13002
        bytes32 m10;
13003
        /// @solidity memory-safe-assembly
13004
        assembly {
13005
            function writeString(pos, w) {
13006
                let length := 0
13007
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13008
                mstore(pos, length)
13009
                let shift := sub(256, shl(3, length))
13010
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13011
            }
13012
            m0 := mload(0x00)
13013
            m1 := mload(0x20)
13014
            m2 := mload(0x40)
13015
            m3 := mload(0x60)
13016
            m4 := mload(0x80)
13017
            m5 := mload(0xa0)
13018
            m6 := mload(0xc0)
13019
            m7 := mload(0xe0)
13020
            m8 := mload(0x100)
13021
            m9 := mload(0x120)
13022
            m10 := mload(0x140)
13023
            // Selector of `log(string,uint256,string,string)`.
13024
            mstore(0x00, 0x5ab84e1f)
13025
            mstore(0x20, 0x80)
13026
            mstore(0x40, p1)
13027
            mstore(0x60, 0xc0)
13028
            mstore(0x80, 0x100)
13029
            writeString(0xa0, p0)
13030
            writeString(0xe0, p2)
13031
            writeString(0x120, p3)
13032
        }
13033
        _sendLogPayload(0x1c, 0x144);
13034
        /// @solidity memory-safe-assembly
13035
        assembly {
13036
            mstore(0x00, m0)
13037
            mstore(0x20, m1)
13038
            mstore(0x40, m2)
13039
            mstore(0x60, m3)
13040
            mstore(0x80, m4)
13041
            mstore(0xa0, m5)
13042
            mstore(0xc0, m6)
13043
            mstore(0xe0, m7)
13044
            mstore(0x100, m8)
13045
            mstore(0x120, m9)
13046
            mstore(0x140, m10)
13047
        }
13048
    }
13049

                            
                        
13050
    function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure {
13051
        bytes32 m0;
13052
        bytes32 m1;
13053
        bytes32 m2;
13054
        bytes32 m3;
13055
        bytes32 m4;
13056
        bytes32 m5;
13057
        bytes32 m6;
13058
        bytes32 m7;
13059
        bytes32 m8;
13060
        /// @solidity memory-safe-assembly
13061
        assembly {
13062
            function writeString(pos, w) {
13063
                let length := 0
13064
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13065
                mstore(pos, length)
13066
                let shift := sub(256, shl(3, length))
13067
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13068
            }
13069
            m0 := mload(0x00)
13070
            m1 := mload(0x20)
13071
            m2 := mload(0x40)
13072
            m3 := mload(0x60)
13073
            m4 := mload(0x80)
13074
            m5 := mload(0xa0)
13075
            m6 := mload(0xc0)
13076
            m7 := mload(0xe0)
13077
            m8 := mload(0x100)
13078
            // Selector of `log(string,string,address,address)`.
13079
            mstore(0x00, 0x439c7bef)
13080
            mstore(0x20, 0x80)
13081
            mstore(0x40, 0xc0)
13082
            mstore(0x60, p2)
13083
            mstore(0x80, p3)
13084
            writeString(0xa0, p0)
13085
            writeString(0xe0, p1)
13086
        }
13087
        _sendLogPayload(0x1c, 0x104);
13088
        /// @solidity memory-safe-assembly
13089
        assembly {
13090
            mstore(0x00, m0)
13091
            mstore(0x20, m1)
13092
            mstore(0x40, m2)
13093
            mstore(0x60, m3)
13094
            mstore(0x80, m4)
13095
            mstore(0xa0, m5)
13096
            mstore(0xc0, m6)
13097
            mstore(0xe0, m7)
13098
            mstore(0x100, m8)
13099
        }
13100
    }
13101

                            
                        
13102
    function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure {
13103
        bytes32 m0;
13104
        bytes32 m1;
13105
        bytes32 m2;
13106
        bytes32 m3;
13107
        bytes32 m4;
13108
        bytes32 m5;
13109
        bytes32 m6;
13110
        bytes32 m7;
13111
        bytes32 m8;
13112
        /// @solidity memory-safe-assembly
13113
        assembly {
13114
            function writeString(pos, w) {
13115
                let length := 0
13116
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13117
                mstore(pos, length)
13118
                let shift := sub(256, shl(3, length))
13119
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13120
            }
13121
            m0 := mload(0x00)
13122
            m1 := mload(0x20)
13123
            m2 := mload(0x40)
13124
            m3 := mload(0x60)
13125
            m4 := mload(0x80)
13126
            m5 := mload(0xa0)
13127
            m6 := mload(0xc0)
13128
            m7 := mload(0xe0)
13129
            m8 := mload(0x100)
13130
            // Selector of `log(string,string,address,bool)`.
13131
            mstore(0x00, 0x5ccd4e37)
13132
            mstore(0x20, 0x80)
13133
            mstore(0x40, 0xc0)
13134
            mstore(0x60, p2)
13135
            mstore(0x80, p3)
13136
            writeString(0xa0, p0)
13137
            writeString(0xe0, p1)
13138
        }
13139
        _sendLogPayload(0x1c, 0x104);
13140
        /// @solidity memory-safe-assembly
13141
        assembly {
13142
            mstore(0x00, m0)
13143
            mstore(0x20, m1)
13144
            mstore(0x40, m2)
13145
            mstore(0x60, m3)
13146
            mstore(0x80, m4)
13147
            mstore(0xa0, m5)
13148
            mstore(0xc0, m6)
13149
            mstore(0xe0, m7)
13150
            mstore(0x100, m8)
13151
        }
13152
    }
13153

                            
                        
13154
    function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure {
13155
        bytes32 m0;
13156
        bytes32 m1;
13157
        bytes32 m2;
13158
        bytes32 m3;
13159
        bytes32 m4;
13160
        bytes32 m5;
13161
        bytes32 m6;
13162
        bytes32 m7;
13163
        bytes32 m8;
13164
        /// @solidity memory-safe-assembly
13165
        assembly {
13166
            function writeString(pos, w) {
13167
                let length := 0
13168
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13169
                mstore(pos, length)
13170
                let shift := sub(256, shl(3, length))
13171
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13172
            }
13173
            m0 := mload(0x00)
13174
            m1 := mload(0x20)
13175
            m2 := mload(0x40)
13176
            m3 := mload(0x60)
13177
            m4 := mload(0x80)
13178
            m5 := mload(0xa0)
13179
            m6 := mload(0xc0)
13180
            m7 := mload(0xe0)
13181
            m8 := mload(0x100)
13182
            // Selector of `log(string,string,address,uint256)`.
13183
            mstore(0x00, 0x7cc3c607)
13184
            mstore(0x20, 0x80)
13185
            mstore(0x40, 0xc0)
13186
            mstore(0x60, p2)
13187
            mstore(0x80, p3)
13188
            writeString(0xa0, p0)
13189
            writeString(0xe0, p1)
13190
        }
13191
        _sendLogPayload(0x1c, 0x104);
13192
        /// @solidity memory-safe-assembly
13193
        assembly {
13194
            mstore(0x00, m0)
13195
            mstore(0x20, m1)
13196
            mstore(0x40, m2)
13197
            mstore(0x60, m3)
13198
            mstore(0x80, m4)
13199
            mstore(0xa0, m5)
13200
            mstore(0xc0, m6)
13201
            mstore(0xe0, m7)
13202
            mstore(0x100, m8)
13203
        }
13204
    }
13205

                            
                        
13206
    function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
13207
        bytes32 m0;
13208
        bytes32 m1;
13209
        bytes32 m2;
13210
        bytes32 m3;
13211
        bytes32 m4;
13212
        bytes32 m5;
13213
        bytes32 m6;
13214
        bytes32 m7;
13215
        bytes32 m8;
13216
        bytes32 m9;
13217
        bytes32 m10;
13218
        /// @solidity memory-safe-assembly
13219
        assembly {
13220
            function writeString(pos, w) {
13221
                let length := 0
13222
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13223
                mstore(pos, length)
13224
                let shift := sub(256, shl(3, length))
13225
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13226
            }
13227
            m0 := mload(0x00)
13228
            m1 := mload(0x20)
13229
            m2 := mload(0x40)
13230
            m3 := mload(0x60)
13231
            m4 := mload(0x80)
13232
            m5 := mload(0xa0)
13233
            m6 := mload(0xc0)
13234
            m7 := mload(0xe0)
13235
            m8 := mload(0x100)
13236
            m9 := mload(0x120)
13237
            m10 := mload(0x140)
13238
            // Selector of `log(string,string,address,string)`.
13239
            mstore(0x00, 0xeb1bff80)
13240
            mstore(0x20, 0x80)
13241
            mstore(0x40, 0xc0)
13242
            mstore(0x60, p2)
13243
            mstore(0x80, 0x100)
13244
            writeString(0xa0, p0)
13245
            writeString(0xe0, p1)
13246
            writeString(0x120, p3)
13247
        }
13248
        _sendLogPayload(0x1c, 0x144);
13249
        /// @solidity memory-safe-assembly
13250
        assembly {
13251
            mstore(0x00, m0)
13252
            mstore(0x20, m1)
13253
            mstore(0x40, m2)
13254
            mstore(0x60, m3)
13255
            mstore(0x80, m4)
13256
            mstore(0xa0, m5)
13257
            mstore(0xc0, m6)
13258
            mstore(0xe0, m7)
13259
            mstore(0x100, m8)
13260
            mstore(0x120, m9)
13261
            mstore(0x140, m10)
13262
        }
13263
    }
13264

                            
                        
13265
    function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure {
13266
        bytes32 m0;
13267
        bytes32 m1;
13268
        bytes32 m2;
13269
        bytes32 m3;
13270
        bytes32 m4;
13271
        bytes32 m5;
13272
        bytes32 m6;
13273
        bytes32 m7;
13274
        bytes32 m8;
13275
        /// @solidity memory-safe-assembly
13276
        assembly {
13277
            function writeString(pos, w) {
13278
                let length := 0
13279
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13280
                mstore(pos, length)
13281
                let shift := sub(256, shl(3, length))
13282
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13283
            }
13284
            m0 := mload(0x00)
13285
            m1 := mload(0x20)
13286
            m2 := mload(0x40)
13287
            m3 := mload(0x60)
13288
            m4 := mload(0x80)
13289
            m5 := mload(0xa0)
13290
            m6 := mload(0xc0)
13291
            m7 := mload(0xe0)
13292
            m8 := mload(0x100)
13293
            // Selector of `log(string,string,bool,address)`.
13294
            mstore(0x00, 0xc371c7db)
13295
            mstore(0x20, 0x80)
13296
            mstore(0x40, 0xc0)
13297
            mstore(0x60, p2)
13298
            mstore(0x80, p3)
13299
            writeString(0xa0, p0)
13300
            writeString(0xe0, p1)
13301
        }
13302
        _sendLogPayload(0x1c, 0x104);
13303
        /// @solidity memory-safe-assembly
13304
        assembly {
13305
            mstore(0x00, m0)
13306
            mstore(0x20, m1)
13307
            mstore(0x40, m2)
13308
            mstore(0x60, m3)
13309
            mstore(0x80, m4)
13310
            mstore(0xa0, m5)
13311
            mstore(0xc0, m6)
13312
            mstore(0xe0, m7)
13313
            mstore(0x100, m8)
13314
        }
13315
    }
13316

                            
                        
13317
    function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure {
13318
        bytes32 m0;
13319
        bytes32 m1;
13320
        bytes32 m2;
13321
        bytes32 m3;
13322
        bytes32 m4;
13323
        bytes32 m5;
13324
        bytes32 m6;
13325
        bytes32 m7;
13326
        bytes32 m8;
13327
        /// @solidity memory-safe-assembly
13328
        assembly {
13329
            function writeString(pos, w) {
13330
                let length := 0
13331
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13332
                mstore(pos, length)
13333
                let shift := sub(256, shl(3, length))
13334
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13335
            }
13336
            m0 := mload(0x00)
13337
            m1 := mload(0x20)
13338
            m2 := mload(0x40)
13339
            m3 := mload(0x60)
13340
            m4 := mload(0x80)
13341
            m5 := mload(0xa0)
13342
            m6 := mload(0xc0)
13343
            m7 := mload(0xe0)
13344
            m8 := mload(0x100)
13345
            // Selector of `log(string,string,bool,bool)`.
13346
            mstore(0x00, 0x40785869)
13347
            mstore(0x20, 0x80)
13348
            mstore(0x40, 0xc0)
13349
            mstore(0x60, p2)
13350
            mstore(0x80, p3)
13351
            writeString(0xa0, p0)
13352
            writeString(0xe0, p1)
13353
        }
13354
        _sendLogPayload(0x1c, 0x104);
13355
        /// @solidity memory-safe-assembly
13356
        assembly {
13357
            mstore(0x00, m0)
13358
            mstore(0x20, m1)
13359
            mstore(0x40, m2)
13360
            mstore(0x60, m3)
13361
            mstore(0x80, m4)
13362
            mstore(0xa0, m5)
13363
            mstore(0xc0, m6)
13364
            mstore(0xe0, m7)
13365
            mstore(0x100, m8)
13366
        }
13367
    }
13368

                            
                        
13369
    function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
13370
        bytes32 m0;
13371
        bytes32 m1;
13372
        bytes32 m2;
13373
        bytes32 m3;
13374
        bytes32 m4;
13375
        bytes32 m5;
13376
        bytes32 m6;
13377
        bytes32 m7;
13378
        bytes32 m8;
13379
        /// @solidity memory-safe-assembly
13380
        assembly {
13381
            function writeString(pos, w) {
13382
                let length := 0
13383
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13384
                mstore(pos, length)
13385
                let shift := sub(256, shl(3, length))
13386
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13387
            }
13388
            m0 := mload(0x00)
13389
            m1 := mload(0x20)
13390
            m2 := mload(0x40)
13391
            m3 := mload(0x60)
13392
            m4 := mload(0x80)
13393
            m5 := mload(0xa0)
13394
            m6 := mload(0xc0)
13395
            m7 := mload(0xe0)
13396
            m8 := mload(0x100)
13397
            // Selector of `log(string,string,bool,uint256)`.
13398
            mstore(0x00, 0xd6aefad2)
13399
            mstore(0x20, 0x80)
13400
            mstore(0x40, 0xc0)
13401
            mstore(0x60, p2)
13402
            mstore(0x80, p3)
13403
            writeString(0xa0, p0)
13404
            writeString(0xe0, p1)
13405
        }
13406
        _sendLogPayload(0x1c, 0x104);
13407
        /// @solidity memory-safe-assembly
13408
        assembly {
13409
            mstore(0x00, m0)
13410
            mstore(0x20, m1)
13411
            mstore(0x40, m2)
13412
            mstore(0x60, m3)
13413
            mstore(0x80, m4)
13414
            mstore(0xa0, m5)
13415
            mstore(0xc0, m6)
13416
            mstore(0xe0, m7)
13417
            mstore(0x100, m8)
13418
        }
13419
    }
13420

                            
                        
13421
    function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
13422
        bytes32 m0;
13423
        bytes32 m1;
13424
        bytes32 m2;
13425
        bytes32 m3;
13426
        bytes32 m4;
13427
        bytes32 m5;
13428
        bytes32 m6;
13429
        bytes32 m7;
13430
        bytes32 m8;
13431
        bytes32 m9;
13432
        bytes32 m10;
13433
        /// @solidity memory-safe-assembly
13434
        assembly {
13435
            function writeString(pos, w) {
13436
                let length := 0
13437
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13438
                mstore(pos, length)
13439
                let shift := sub(256, shl(3, length))
13440
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13441
            }
13442
            m0 := mload(0x00)
13443
            m1 := mload(0x20)
13444
            m2 := mload(0x40)
13445
            m3 := mload(0x60)
13446
            m4 := mload(0x80)
13447
            m5 := mload(0xa0)
13448
            m6 := mload(0xc0)
13449
            m7 := mload(0xe0)
13450
            m8 := mload(0x100)
13451
            m9 := mload(0x120)
13452
            m10 := mload(0x140)
13453
            // Selector of `log(string,string,bool,string)`.
13454
            mstore(0x00, 0x5e84b0ea)
13455
            mstore(0x20, 0x80)
13456
            mstore(0x40, 0xc0)
13457
            mstore(0x60, p2)
13458
            mstore(0x80, 0x100)
13459
            writeString(0xa0, p0)
13460
            writeString(0xe0, p1)
13461
            writeString(0x120, p3)
13462
        }
13463
        _sendLogPayload(0x1c, 0x144);
13464
        /// @solidity memory-safe-assembly
13465
        assembly {
13466
            mstore(0x00, m0)
13467
            mstore(0x20, m1)
13468
            mstore(0x40, m2)
13469
            mstore(0x60, m3)
13470
            mstore(0x80, m4)
13471
            mstore(0xa0, m5)
13472
            mstore(0xc0, m6)
13473
            mstore(0xe0, m7)
13474
            mstore(0x100, m8)
13475
            mstore(0x120, m9)
13476
            mstore(0x140, m10)
13477
        }
13478
    }
13479

                            
                        
13480
    function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure {
13481
        bytes32 m0;
13482
        bytes32 m1;
13483
        bytes32 m2;
13484
        bytes32 m3;
13485
        bytes32 m4;
13486
        bytes32 m5;
13487
        bytes32 m6;
13488
        bytes32 m7;
13489
        bytes32 m8;
13490
        /// @solidity memory-safe-assembly
13491
        assembly {
13492
            function writeString(pos, w) {
13493
                let length := 0
13494
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13495
                mstore(pos, length)
13496
                let shift := sub(256, shl(3, length))
13497
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13498
            }
13499
            m0 := mload(0x00)
13500
            m1 := mload(0x20)
13501
            m2 := mload(0x40)
13502
            m3 := mload(0x60)
13503
            m4 := mload(0x80)
13504
            m5 := mload(0xa0)
13505
            m6 := mload(0xc0)
13506
            m7 := mload(0xe0)
13507
            m8 := mload(0x100)
13508
            // Selector of `log(string,string,uint256,address)`.
13509
            mstore(0x00, 0x1023f7b2)
13510
            mstore(0x20, 0x80)
13511
            mstore(0x40, 0xc0)
13512
            mstore(0x60, p2)
13513
            mstore(0x80, p3)
13514
            writeString(0xa0, p0)
13515
            writeString(0xe0, p1)
13516
        }
13517
        _sendLogPayload(0x1c, 0x104);
13518
        /// @solidity memory-safe-assembly
13519
        assembly {
13520
            mstore(0x00, m0)
13521
            mstore(0x20, m1)
13522
            mstore(0x40, m2)
13523
            mstore(0x60, m3)
13524
            mstore(0x80, m4)
13525
            mstore(0xa0, m5)
13526
            mstore(0xc0, m6)
13527
            mstore(0xe0, m7)
13528
            mstore(0x100, m8)
13529
        }
13530
    }
13531

                            
                        
13532
    function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
13533
        bytes32 m0;
13534
        bytes32 m1;
13535
        bytes32 m2;
13536
        bytes32 m3;
13537
        bytes32 m4;
13538
        bytes32 m5;
13539
        bytes32 m6;
13540
        bytes32 m7;
13541
        bytes32 m8;
13542
        /// @solidity memory-safe-assembly
13543
        assembly {
13544
            function writeString(pos, w) {
13545
                let length := 0
13546
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13547
                mstore(pos, length)
13548
                let shift := sub(256, shl(3, length))
13549
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13550
            }
13551
            m0 := mload(0x00)
13552
            m1 := mload(0x20)
13553
            m2 := mload(0x40)
13554
            m3 := mload(0x60)
13555
            m4 := mload(0x80)
13556
            m5 := mload(0xa0)
13557
            m6 := mload(0xc0)
13558
            m7 := mload(0xe0)
13559
            m8 := mload(0x100)
13560
            // Selector of `log(string,string,uint256,bool)`.
13561
            mstore(0x00, 0xc3a8a654)
13562
            mstore(0x20, 0x80)
13563
            mstore(0x40, 0xc0)
13564
            mstore(0x60, p2)
13565
            mstore(0x80, p3)
13566
            writeString(0xa0, p0)
13567
            writeString(0xe0, p1)
13568
        }
13569
        _sendLogPayload(0x1c, 0x104);
13570
        /// @solidity memory-safe-assembly
13571
        assembly {
13572
            mstore(0x00, m0)
13573
            mstore(0x20, m1)
13574
            mstore(0x40, m2)
13575
            mstore(0x60, m3)
13576
            mstore(0x80, m4)
13577
            mstore(0xa0, m5)
13578
            mstore(0xc0, m6)
13579
            mstore(0xe0, m7)
13580
            mstore(0x100, m8)
13581
        }
13582
    }
13583

                            
                        
13584
    function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
13585
        bytes32 m0;
13586
        bytes32 m1;
13587
        bytes32 m2;
13588
        bytes32 m3;
13589
        bytes32 m4;
13590
        bytes32 m5;
13591
        bytes32 m6;
13592
        bytes32 m7;
13593
        bytes32 m8;
13594
        /// @solidity memory-safe-assembly
13595
        assembly {
13596
            function writeString(pos, w) {
13597
                let length := 0
13598
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13599
                mstore(pos, length)
13600
                let shift := sub(256, shl(3, length))
13601
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13602
            }
13603
            m0 := mload(0x00)
13604
            m1 := mload(0x20)
13605
            m2 := mload(0x40)
13606
            m3 := mload(0x60)
13607
            m4 := mload(0x80)
13608
            m5 := mload(0xa0)
13609
            m6 := mload(0xc0)
13610
            m7 := mload(0xe0)
13611
            m8 := mload(0x100)
13612
            // Selector of `log(string,string,uint256,uint256)`.
13613
            mstore(0x00, 0xf45d7d2c)
13614
            mstore(0x20, 0x80)
13615
            mstore(0x40, 0xc0)
13616
            mstore(0x60, p2)
13617
            mstore(0x80, p3)
13618
            writeString(0xa0, p0)
13619
            writeString(0xe0, p1)
13620
        }
13621
        _sendLogPayload(0x1c, 0x104);
13622
        /// @solidity memory-safe-assembly
13623
        assembly {
13624
            mstore(0x00, m0)
13625
            mstore(0x20, m1)
13626
            mstore(0x40, m2)
13627
            mstore(0x60, m3)
13628
            mstore(0x80, m4)
13629
            mstore(0xa0, m5)
13630
            mstore(0xc0, m6)
13631
            mstore(0xe0, m7)
13632
            mstore(0x100, m8)
13633
        }
13634
    }
13635

                            
                        
13636
    function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
13637
        bytes32 m0;
13638
        bytes32 m1;
13639
        bytes32 m2;
13640
        bytes32 m3;
13641
        bytes32 m4;
13642
        bytes32 m5;
13643
        bytes32 m6;
13644
        bytes32 m7;
13645
        bytes32 m8;
13646
        bytes32 m9;
13647
        bytes32 m10;
13648
        /// @solidity memory-safe-assembly
13649
        assembly {
13650
            function writeString(pos, w) {
13651
                let length := 0
13652
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13653
                mstore(pos, length)
13654
                let shift := sub(256, shl(3, length))
13655
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13656
            }
13657
            m0 := mload(0x00)
13658
            m1 := mload(0x20)
13659
            m2 := mload(0x40)
13660
            m3 := mload(0x60)
13661
            m4 := mload(0x80)
13662
            m5 := mload(0xa0)
13663
            m6 := mload(0xc0)
13664
            m7 := mload(0xe0)
13665
            m8 := mload(0x100)
13666
            m9 := mload(0x120)
13667
            m10 := mload(0x140)
13668
            // Selector of `log(string,string,uint256,string)`.
13669
            mstore(0x00, 0x5d1a971a)
13670
            mstore(0x20, 0x80)
13671
            mstore(0x40, 0xc0)
13672
            mstore(0x60, p2)
13673
            mstore(0x80, 0x100)
13674
            writeString(0xa0, p0)
13675
            writeString(0xe0, p1)
13676
            writeString(0x120, p3)
13677
        }
13678
        _sendLogPayload(0x1c, 0x144);
13679
        /// @solidity memory-safe-assembly
13680
        assembly {
13681
            mstore(0x00, m0)
13682
            mstore(0x20, m1)
13683
            mstore(0x40, m2)
13684
            mstore(0x60, m3)
13685
            mstore(0x80, m4)
13686
            mstore(0xa0, m5)
13687
            mstore(0xc0, m6)
13688
            mstore(0xe0, m7)
13689
            mstore(0x100, m8)
13690
            mstore(0x120, m9)
13691
            mstore(0x140, m10)
13692
        }
13693
    }
13694

                            
                        
13695
    function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
13696
        bytes32 m0;
13697
        bytes32 m1;
13698
        bytes32 m2;
13699
        bytes32 m3;
13700
        bytes32 m4;
13701
        bytes32 m5;
13702
        bytes32 m6;
13703
        bytes32 m7;
13704
        bytes32 m8;
13705
        bytes32 m9;
13706
        bytes32 m10;
13707
        /// @solidity memory-safe-assembly
13708
        assembly {
13709
            function writeString(pos, w) {
13710
                let length := 0
13711
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13712
                mstore(pos, length)
13713
                let shift := sub(256, shl(3, length))
13714
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13715
            }
13716
            m0 := mload(0x00)
13717
            m1 := mload(0x20)
13718
            m2 := mload(0x40)
13719
            m3 := mload(0x60)
13720
            m4 := mload(0x80)
13721
            m5 := mload(0xa0)
13722
            m6 := mload(0xc0)
13723
            m7 := mload(0xe0)
13724
            m8 := mload(0x100)
13725
            m9 := mload(0x120)
13726
            m10 := mload(0x140)
13727
            // Selector of `log(string,string,string,address)`.
13728
            mstore(0x00, 0x6d572f44)
13729
            mstore(0x20, 0x80)
13730
            mstore(0x40, 0xc0)
13731
            mstore(0x60, 0x100)
13732
            mstore(0x80, p3)
13733
            writeString(0xa0, p0)
13734
            writeString(0xe0, p1)
13735
            writeString(0x120, p2)
13736
        }
13737
        _sendLogPayload(0x1c, 0x144);
13738
        /// @solidity memory-safe-assembly
13739
        assembly {
13740
            mstore(0x00, m0)
13741
            mstore(0x20, m1)
13742
            mstore(0x40, m2)
13743
            mstore(0x60, m3)
13744
            mstore(0x80, m4)
13745
            mstore(0xa0, m5)
13746
            mstore(0xc0, m6)
13747
            mstore(0xe0, m7)
13748
            mstore(0x100, m8)
13749
            mstore(0x120, m9)
13750
            mstore(0x140, m10)
13751
        }
13752
    }
13753

                            
                        
13754
    function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
13755
        bytes32 m0;
13756
        bytes32 m1;
13757
        bytes32 m2;
13758
        bytes32 m3;
13759
        bytes32 m4;
13760
        bytes32 m5;
13761
        bytes32 m6;
13762
        bytes32 m7;
13763
        bytes32 m8;
13764
        bytes32 m9;
13765
        bytes32 m10;
13766
        /// @solidity memory-safe-assembly
13767
        assembly {
13768
            function writeString(pos, w) {
13769
                let length := 0
13770
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13771
                mstore(pos, length)
13772
                let shift := sub(256, shl(3, length))
13773
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13774
            }
13775
            m0 := mload(0x00)
13776
            m1 := mload(0x20)
13777
            m2 := mload(0x40)
13778
            m3 := mload(0x60)
13779
            m4 := mload(0x80)
13780
            m5 := mload(0xa0)
13781
            m6 := mload(0xc0)
13782
            m7 := mload(0xe0)
13783
            m8 := mload(0x100)
13784
            m9 := mload(0x120)
13785
            m10 := mload(0x140)
13786
            // Selector of `log(string,string,string,bool)`.
13787
            mstore(0x00, 0x2c1754ed)
13788
            mstore(0x20, 0x80)
13789
            mstore(0x40, 0xc0)
13790
            mstore(0x60, 0x100)
13791
            mstore(0x80, p3)
13792
            writeString(0xa0, p0)
13793
            writeString(0xe0, p1)
13794
            writeString(0x120, p2)
13795
        }
13796
        _sendLogPayload(0x1c, 0x144);
13797
        /// @solidity memory-safe-assembly
13798
        assembly {
13799
            mstore(0x00, m0)
13800
            mstore(0x20, m1)
13801
            mstore(0x40, m2)
13802
            mstore(0x60, m3)
13803
            mstore(0x80, m4)
13804
            mstore(0xa0, m5)
13805
            mstore(0xc0, m6)
13806
            mstore(0xe0, m7)
13807
            mstore(0x100, m8)
13808
            mstore(0x120, m9)
13809
            mstore(0x140, m10)
13810
        }
13811
    }
13812

                            
                        
13813
    function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
13814
        bytes32 m0;
13815
        bytes32 m1;
13816
        bytes32 m2;
13817
        bytes32 m3;
13818
        bytes32 m4;
13819
        bytes32 m5;
13820
        bytes32 m6;
13821
        bytes32 m7;
13822
        bytes32 m8;
13823
        bytes32 m9;
13824
        bytes32 m10;
13825
        /// @solidity memory-safe-assembly
13826
        assembly {
13827
            function writeString(pos, w) {
13828
                let length := 0
13829
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13830
                mstore(pos, length)
13831
                let shift := sub(256, shl(3, length))
13832
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13833
            }
13834
            m0 := mload(0x00)
13835
            m1 := mload(0x20)
13836
            m2 := mload(0x40)
13837
            m3 := mload(0x60)
13838
            m4 := mload(0x80)
13839
            m5 := mload(0xa0)
13840
            m6 := mload(0xc0)
13841
            m7 := mload(0xe0)
13842
            m8 := mload(0x100)
13843
            m9 := mload(0x120)
13844
            m10 := mload(0x140)
13845
            // Selector of `log(string,string,string,uint256)`.
13846
            mstore(0x00, 0x8eafb02b)
13847
            mstore(0x20, 0x80)
13848
            mstore(0x40, 0xc0)
13849
            mstore(0x60, 0x100)
13850
            mstore(0x80, p3)
13851
            writeString(0xa0, p0)
13852
            writeString(0xe0, p1)
13853
            writeString(0x120, p2)
13854
        }
13855
        _sendLogPayload(0x1c, 0x144);
13856
        /// @solidity memory-safe-assembly
13857
        assembly {
13858
            mstore(0x00, m0)
13859
            mstore(0x20, m1)
13860
            mstore(0x40, m2)
13861
            mstore(0x60, m3)
13862
            mstore(0x80, m4)
13863
            mstore(0xa0, m5)
13864
            mstore(0xc0, m6)
13865
            mstore(0xe0, m7)
13866
            mstore(0x100, m8)
13867
            mstore(0x120, m9)
13868
            mstore(0x140, m10)
13869
        }
13870
    }
13871

                            
                        
13872
    function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
13873
        bytes32 m0;
13874
        bytes32 m1;
13875
        bytes32 m2;
13876
        bytes32 m3;
13877
        bytes32 m4;
13878
        bytes32 m5;
13879
        bytes32 m6;
13880
        bytes32 m7;
13881
        bytes32 m8;
13882
        bytes32 m9;
13883
        bytes32 m10;
13884
        bytes32 m11;
13885
        bytes32 m12;
13886
        /// @solidity memory-safe-assembly
13887
        assembly {
13888
            function writeString(pos, w) {
13889
                let length := 0
13890
                for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
13891
                mstore(pos, length)
13892
                let shift := sub(256, shl(3, length))
13893
                mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
13894
            }
13895
            m0 := mload(0x00)
13896
            m1 := mload(0x20)
13897
            m2 := mload(0x40)
13898
            m3 := mload(0x60)
13899
            m4 := mload(0x80)
13900
            m5 := mload(0xa0)
13901
            m6 := mload(0xc0)
13902
            m7 := mload(0xe0)
13903
            m8 := mload(0x100)
13904
            m9 := mload(0x120)
13905
            m10 := mload(0x140)
13906
            m11 := mload(0x160)
13907
            m12 := mload(0x180)
13908
            // Selector of `log(string,string,string,string)`.
13909
            mstore(0x00, 0xde68f20a)
13910
            mstore(0x20, 0x80)
13911
            mstore(0x40, 0xc0)
13912
            mstore(0x60, 0x100)
13913
            mstore(0x80, 0x140)
13914
            writeString(0xa0, p0)
13915
            writeString(0xe0, p1)
13916
            writeString(0x120, p2)
13917
            writeString(0x160, p3)
13918
        }
13919
        _sendLogPayload(0x1c, 0x184);
13920
        /// @solidity memory-safe-assembly
13921
        assembly {
13922
            mstore(0x00, m0)
13923
            mstore(0x20, m1)
13924
            mstore(0x40, m2)
13925
            mstore(0x60, m3)
13926
            mstore(0x80, m4)
13927
            mstore(0xa0, m5)
13928
            mstore(0xc0, m6)
13929
            mstore(0xe0, m7)
13930
            mstore(0x100, m8)
13931
            mstore(0x120, m9)
13932
            mstore(0x140, m10)
13933
            mstore(0x160, m11)
13934
            mstore(0x180, m12)
13935
        }
13936
    }
13937
}
13938

                            
                        

Lines covered: 0 / 8 (0.0%)

1
// SPDX-License-Identifier: MIT
2
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)
3

                            
                        
4
pragma solidity ^0.8.20;
5

                            
                        
6
/**
7
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
8
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
9
 * be specified by overriding the virtual {_implementation} function.
10
 *
11
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
12
 * different contract through the {_delegate} function.
13
 *
14
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
15
 */
16
abstract contract Proxy {
17
    /**
18
     * @dev Delegates the current call to `implementation`.
19
     *
20
     * This function does not return to its internal call site, it will return directly to the external caller.
21
     */
22
    function _delegate(address implementation) internal virtual {
23
        assembly {
24
            // Copy msg.data. We take full control of memory in this inline assembly
25
            // block because it will not return to Solidity code. We overwrite the
26
            // Solidity scratch pad at memory position 0.
27
            calldatacopy(0, 0, calldatasize())
28

                            
                        
29
            // Call the implementation.
30
            // out and outsize are 0 because we don't know the size yet.
31
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
32

                            
                        
33
            // Copy the returned data.
34
            returndatacopy(0, 0, returndatasize())
35

                            
                        
36
            switch result
37
            // delegatecall returns 0 on error.
38
            case 0 {
39
                revert(0, returndatasize())
40
            }
41
            default {
42
                return(0, returndatasize())
43
            }
44
        }
45
    }
46

                            
                        
47
    /**
48
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback
49
     * function and {_fallback} should delegate.
50
     */
51
    function _implementation() internal view virtual returns (address);
52

                            
                        
53
    /**
54
     * @dev Delegates the current call to the address returned by `_implementation()`.
55
     *
56
     * This function does not return to its internal call site, it will return directly to the external caller.
57
     */
58
    function _fallback() internal virtual {
59
        _delegate(_implementation());
60
    }
61

                            
                        
62
    /**
63
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
64
     * function in the contract matches the call data.
65
     */
66
    fallback() external payable virtual {
67
        _fallback();
68
    }
69
}
70

                            
                        

Lines covered: 4 / 6 (66.7%)

1
// SPDX-License-Identifier: AGPL-3.0-only
2
pragma solidity >=0.8.0;
3

                            
                        
4
/// @notice Simple single owner authorization mixin.
5
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
6
abstract contract Owned {
7
    /*//////////////////////////////////////////////////////////////
8
                                 EVENTS
9
    //////////////////////////////////////////////////////////////*/
10

                            
                        
11
    event OwnershipTransferred(address indexed user, address indexed newOwner);
12

                            
                        
13
    /*//////////////////////////////////////////////////////////////
14
                            OWNERSHIP STORAGE
15
    //////////////////////////////////////////////////////////////*/
16

                            
                        
17
√ 4
⟳ 4
    address public owner;
18

                            
                        
19
    modifier onlyOwner() virtual {
20
√ 5
⟳ 5
        require(msg.sender == owner, "UNAUTHORIZED");
21

                            
                        
22
        _;
23
    }
24

                            
                        
25
    /*//////////////////////////////////////////////////////////////
26
                               CONSTRUCTOR
27
    //////////////////////////////////////////////////////////////*/
28

                            
                        
29
    constructor(address _owner) {
30
√ 3
        owner = _owner;
31

                            
                        
32
√ 5
        emit OwnershipTransferred(address(0), _owner);
33
    }
34

                            
                        
35
    /*//////////////////////////////////////////////////////////////
36
                             OWNERSHIP LOGIC
37
    //////////////////////////////////////////////////////////////*/
38

                            
                        
39
    function transferOwnership(address newOwner) public virtual onlyOwner {
40
        owner = newOwner;
41

                            
                        
42
        emit OwnershipTransferred(msg.sender, newOwner);
43
    }
44
}
45

                            
                        

Lines covered: 2 / 3 (66.7%)

1
// SPDX-License-Identifier: AGPL-3.0-only
2
pragma solidity >=0.8.0;
3

                            
                        
4
import {ERC20} from "../../../tokens/ERC20.sol";
5

                            
                        
6
contract MockERC20 is ERC20 {
7
    constructor(
8
        string memory _name,
9
        string memory _symbol,
10
        uint8 _decimals
11
√ 4
    ) ERC20(_name, _symbol, _decimals) {}
12

                            
                        
13
    function mint(address to, uint256 value) public virtual {
14
√ 3
        _mint(to, value);
15
    }
16

                            
                        
17
    function burn(address from, uint256 value) public virtual {
18
        _burn(from, value);
19
    }
20
}
21

                            
                        

Lines covered: 32 / 49 (65.3%)

1
// SPDX-License-Identifier: AGPL-3.0-only
2
pragma solidity >=0.8.0;
3

                            
                        
4
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
5
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
6
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
7
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
8
abstract contract ERC20 {
9
    /*//////////////////////////////////////////////////////////////
10
                                 EVENTS
11
    //////////////////////////////////////////////////////////////*/
12

                            
                        
13
    event Transfer(address indexed from, address indexed to, uint256 amount);
14

                            
                        
15
    event Approval(address indexed owner, address indexed spender, uint256 amount);
16

                            
                        
17
    /*//////////////////////////////////////////////////////////////
18
                            METADATA STORAGE
19
    //////////////////////////////////////////////////////////////*/
20

                            
                        
21
√ 8
⟳ 8
    string public name;
22

                            
                        
23
    string public symbol;
24

                            
                        
25
    uint8 public immutable decimals;
26

                            
                        
27
    /*//////////////////////////////////////////////////////////////
28
                              ERC20 STORAGE
29
    //////////////////////////////////////////////////////////////*/
30

                            
                        
31
√ 4
⟳ 4
    uint256 public totalSupply;
32

                            
                        
33
√ 21
⟳ 21
    mapping(address => uint256) public balanceOf;
34

                            
                        
35
    mapping(address => mapping(address => uint256)) public allowance;
36

                            
                        
37
    /*//////////////////////////////////////////////////////////////
38
                            EIP-2612 STORAGE
39
    //////////////////////////////////////////////////////////////*/
40

                            
                        
41
    uint256 internal immutable INITIAL_CHAIN_ID;
42

                            
                        
43
    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
44

                            
                        
45
    mapping(address => uint256) public nonces;
46

                            
                        
47
    /*//////////////////////////////////////////////////////////////
48
                               CONSTRUCTOR
49
    //////////////////////////////////////////////////////////////*/
50

                            
                        
51
    constructor(
52
        string memory _name,
53
        string memory _symbol,
54
        uint8 _decimals
55
    ) {
56
√ 2
        name = _name;
57
√ 3
        symbol = _symbol;
58
√ 5
        decimals = _decimals;
59

                            
                        
60
√ 1
        INITIAL_CHAIN_ID = block.chainid;
61
√ 1
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
62
    }
63

                            
                        
64
    /*//////////////////////////////////////////////////////////////
65
                               ERC20 LOGIC
66
    //////////////////////////////////////////////////////////////*/
67

                            
                        
68
√ 3
    function approve(address spender, uint256 amount) public virtual returns (bool) {
69
√ 3
        allowance[msg.sender][spender] = amount;
70

                            
                        
71
√ 13
⟳ 8
        emit Approval(msg.sender, spender, amount);
72

                            
                        
73
√ 1
⟳ 1
        return true;
74
    }
75

                            
                        
76
√ 3
⟳ 3
    function transfer(address to, uint256 amount) public virtual returns (bool) {
77
√ 6
⟳ 6
        balanceOf[msg.sender] -= amount;
78

                            
                        
79
        // Cannot overflow because the sum of all user
80
        // balances can't exceed the max uint256 value.
81
        unchecked {
82
√ 2
⟳ 2
            balanceOf[to] += amount;
83
        }
84

                            
                        
85
√ 2
⟳ 2
        emit Transfer(msg.sender, to, amount);
86

                            
                        
87
        return true;
88
    }
89

                            
                        
90
    function transferFrom(
91
        address from,
92
        address to,
93
        uint256 amount
94
√ 1
⟳ 1
    ) public virtual returns (bool) {
95
√ 2
⟳ 2
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
96

                            
                        
97
√ 5
⟳ 5
        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
98

                            
                        
99
√ 5
⟳ 5
        balanceOf[from] -= amount;
100

                            
                        
101
        // Cannot overflow because the sum of all user
102
        // balances can't exceed the max uint256 value.
103
        unchecked {
104
√ 2
⟳ 2
            balanceOf[to] += amount;
105
        }
106

                            
                        
107
√ 16
⟳ 16
        emit Transfer(from, to, amount);
108

                            
                        
109
√ 2
⟳ 2
        return true;
110
    }
111

                            
                        
112
    /*//////////////////////////////////////////////////////////////
113
                             EIP-2612 LOGIC
114
    //////////////////////////////////////////////////////////////*/
115

                            
                        
116
    function permit(
117
        address owner,
118
        address spender,
119
        uint256 value,
120
        uint256 deadline,
121
        uint8 v,
122
        bytes32 r,
123
        bytes32 s
124
    ) public virtual {
125
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
126

                            
                        
127
        // Unchecked because the only math done is incrementing
128
        // the owner's nonce which cannot realistically overflow.
129
        unchecked {
130
            address recoveredAddress = ecrecover(
131
                keccak256(
132
                    abi.encodePacked(
133
                        "\x19\x01",
134
                        DOMAIN_SEPARATOR(),
135
                        keccak256(
136
                            abi.encode(
137
                                keccak256(
138
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
139
                                ),
140
                                owner,
141
                                spender,
142
                                value,
143
                                nonces[owner]++,
144
                                deadline
145
                            )
146
                        )
147
                    )
148
                ),
149
                v,
150
                r,
151
                s
152
            );
153

                            
                        
154
            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
155

                            
                        
156
            allowance[recoveredAddress][spender] = value;
157
        }
158

                            
                        
159
        emit Approval(owner, spender, value);
160
    }
161

                            
                        
162
    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
163
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
164
    }
165

                            
                        
166
√ 1
    function computeDomainSeparator() internal view virtual returns (bytes32) {
167
        return
168
            keccak256(
169
                abi.encode(
170
√ 1
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
171
√ 1
                    keccak256(bytes(name)),
172
√ 1
                    keccak256("1"),
173
√ 1
                    block.chainid,
174
√ 1
                    address(this)
175
                )
176
            );
177
    }
178

                            
                        
179
    /*//////////////////////////////////////////////////////////////
180
                        INTERNAL MINT/BURN LOGIC
181
    //////////////////////////////////////////////////////////////*/
182

                            
                        
183
    function _mint(address to, uint256 amount) internal virtual {
184
√ 3
        totalSupply += amount;
185

                            
                        
186
        // Cannot overflow because the sum of all user
187
        // balances can't exceed the max uint256 value.
188
        unchecked {
189
√ 1
            balanceOf[to] += amount;
190
        }
191

                            
                        
192
√ 11
        emit Transfer(address(0), to, amount);
193
    }
194

                            
                        
195
    function _burn(address from, uint256 amount) internal virtual {
196
        balanceOf[from] -= amount;
197

                            
                        
198
        // Cannot underflow because a user's balance
199
        // will never be larger than the total supply.
200
        unchecked {
201
            totalSupply -= amount;
202
        }
203

                            
                        
204
        emit Transfer(from, address(0), amount);
205
    }
206
}
207

                            
                        

Lines covered: 0 / 8 (0.0%)

1
// SPDX-License-Identifier: AGPL-3.0-only
2
pragma solidity >=0.8.0;
3

                            
                        
4
/// @notice Arithmetic library with operations for fixed-point numbers.
5
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
6
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
7
library FixedPointMathLib {
8
    /*//////////////////////////////////////////////////////////////
9
                    SIMPLIFIED FIXED POINT OPERATIONS
10
    //////////////////////////////////////////////////////////////*/
11

                            
                        
12
    uint256 internal constant MAX_UINT256 = 2**256 - 1;
13

                            
                        
14
    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.
15

                            
                        
16
    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
17
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
18
    }
19

                            
                        
20
    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
21
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
22
    }
23

                            
                        
24
    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
25
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
26
    }
27

                            
                        
28
    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
29
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
30
    }
31

                            
                        
32
    /*//////////////////////////////////////////////////////////////
33
                    LOW LEVEL FIXED POINT OPERATIONS
34
    //////////////////////////////////////////////////////////////*/
35

                            
                        
36
    function mulDivDown(
37
        uint256 x,
38
        uint256 y,
39
        uint256 denominator
40
    ) internal pure returns (uint256 z) {
41
        /// @solidity memory-safe-assembly
42
        assembly {
43
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
44
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
45
                revert(0, 0)
46
            }
47

                            
                        
48
            // Divide x * y by the denominator.
49
            z := div(mul(x, y), denominator)
50
        }
51
    }
52

                            
                        
53
    function mulDivUp(
54
        uint256 x,
55
        uint256 y,
56
        uint256 denominator
57
    ) internal pure returns (uint256 z) {
58
        /// @solidity memory-safe-assembly
59
        assembly {
60
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
61
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
62
                revert(0, 0)
63
            }
64

                            
                        
65
            // If x * y modulo the denominator is strictly greater than 0,
66
            // 1 is added to round up the division of x * y by the denominator.
67
            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
68
        }
69
    }
70

                            
                        
71
    function rpow(
72
        uint256 x,
73
        uint256 n,
74
        uint256 scalar
75
    ) internal pure returns (uint256 z) {
76
        /// @solidity memory-safe-assembly
77
        assembly {
78
            switch x
79
            case 0 {
80
                switch n
81
                case 0 {
82
                    // 0 ** 0 = 1
83
                    z := scalar
84
                }
85
                default {
86
                    // 0 ** n = 0
87
                    z := 0
88
                }
89
            }
90
            default {
91
                switch mod(n, 2)
92
                case 0 {
93
                    // If n is even, store scalar in z for now.
94
                    z := scalar
95
                }
96
                default {
97
                    // If n is odd, store x in z for now.
98
                    z := x
99
                }
100

                            
                        
101
                // Shifting right by 1 is like dividing by 2.
102
                let half := shr(1, scalar)
103

                            
                        
104
                for {
105
                    // Shift n right by 1 before looping to halve it.
106
                    n := shr(1, n)
107
                } n {
108
                    // Shift n right by 1 each iteration to halve it.
109
                    n := shr(1, n)
110
                } {
111
                    // Revert immediately if x ** 2 would overflow.
112
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
113
                    if shr(128, x) {
114
                        revert(0, 0)
115
                    }
116

                            
                        
117
                    // Store x squared.
118
                    let xx := mul(x, x)
119

                            
                        
120
                    // Round to the nearest number.
121
                    let xxRound := add(xx, half)
122

                            
                        
123
                    // Revert if xx + half overflowed.
124
                    if lt(xxRound, xx) {
125
                        revert(0, 0)
126
                    }
127

                            
                        
128
                    // Set x to scaled xxRound.
129
                    x := div(xxRound, scalar)
130

                            
                        
131
                    // If n is even:
132
                    if mod(n, 2) {
133
                        // Compute z * x.
134
                        let zx := mul(z, x)
135

                            
                        
136
                        // If z * x overflowed:
137
                        if iszero(eq(div(zx, x), z)) {
138
                            // Revert if x is non-zero.
139
                            if iszero(iszero(x)) {
140
                                revert(0, 0)
141
                            }
142
                        }
143

                            
                        
144
                        // Round to the nearest number.
145
                        let zxRound := add(zx, half)
146

                            
                        
147
                        // Revert if zx + half overflowed.
148
                        if lt(zxRound, zx) {
149
                            revert(0, 0)
150
                        }
151

                            
                        
152
                        // Return properly scaled zxRound.
153
                        z := div(zxRound, scalar)
154
                    }
155
                }
156
            }
157
        }
158
    }
159

                            
                        
160
    /*//////////////////////////////////////////////////////////////
161
                        GENERAL NUMBER UTILITIES
162
    //////////////////////////////////////////////////////////////*/
163

                            
                        
164
    function sqrt(uint256 x) internal pure returns (uint256 z) {
165
        /// @solidity memory-safe-assembly
166
        assembly {
167
            let y := x // We start y at x, which will help us make our initial estimate.
168

                            
                        
169
            z := 181 // The "correct" value is 1, but this saves a multiplication later.
170

                            
                        
171
            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
172
            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.
173

                            
                        
174
            // We check y >= 2^(k + 8) but shift right by k bits
175
            // each branch to ensure that if x >= 256, then y >= 256.
176
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
177
                y := shr(128, y)
178
                z := shl(64, z)
179
            }
180
            if iszero(lt(y, 0x1000000000000000000)) {
181
                y := shr(64, y)
182
                z := shl(32, z)
183
            }
184
            if iszero(lt(y, 0x10000000000)) {
185
                y := shr(32, y)
186
                z := shl(16, z)
187
            }
188
            if iszero(lt(y, 0x1000000)) {
189
                y := shr(16, y)
190
                z := shl(8, z)
191
            }
192

                            
                        
193
            // Goal was to get z*z*y within a small factor of x. More iterations could
194
            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).
195
            // We ensured y >= 256 so that the relative difference between y and y+1 is small.
196
            // That's not possible if x < 256 but we can just verify those cases exhaustively.
197

                            
                        
198
            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
199
            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
200
            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.
201

                            
                        
202
            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
203
            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.
204

                            
                        
205
            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
206
            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.
207

                            
                        
208
            // There is no overflow risk here since y < 2^136 after the first branch above.
209
            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.
210

                            
                        
211
            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
212
            z := shr(1, add(z, div(x, z)))
213
            z := shr(1, add(z, div(x, z)))
214
            z := shr(1, add(z, div(x, z)))
215
            z := shr(1, add(z, div(x, z)))
216
            z := shr(1, add(z, div(x, z)))
217
            z := shr(1, add(z, div(x, z)))
218
            z := shr(1, add(z, div(x, z)))
219

                            
                        
220
            // If x+1 is a perfect square, the Babylonian method cycles between
221
            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
222
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
223
            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
224
            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.
225
            z := sub(z, lt(div(x, z), z))
226
        }
227
    }
228

                            
                        
229
    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
230
        /// @solidity memory-safe-assembly
231
        assembly {
232
            // Mod x by y. Note this will return
233
            // 0 instead of reverting if y is zero.
234
            z := mod(x, y)
235
        }
236
    }
237

                            
                        
238
    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
239
        /// @solidity memory-safe-assembly
240
        assembly {
241
            // Divide x by y. Note this will return
242
            // 0 instead of reverting if y is zero.
243
            r := div(x, y)
244
        }
245
    }
246

                            
                        
247
    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
248
        /// @solidity memory-safe-assembly
249
        assembly {
250
            // Add 1 to x * y if x % y > 0. Note this will
251
            // return 0 instead of reverting if y is zero.
252
            z := add(gt(mod(x, y), 0), div(x, y))
253
        }
254
    }
255
}
256

                            
                        

Lines covered: 5 / 30 (16.7%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {IERC6909Claims} from "./interfaces/external/IERC6909Claims.sol";
5

                            
                        
6
/// @notice Minimalist and gas efficient standard ERC6909 implementation.
7
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC6909.sol)
8
/// @dev Copied from the commit at 4b47a19038b798b4a33d9749d25e570443520647
9
/// @dev This contract has been modified from the implementation at the above link.
10
abstract contract ERC6909 is IERC6909Claims {
11
    /*//////////////////////////////////////////////////////////////
12
                             ERC6909 STORAGE
13
    //////////////////////////////////////////////////////////////*/
14

                            
                        
15
    mapping(address owner => mapping(address operator => bool isOperator)) public isOperator;
16

                            
                        
17
√ 49
⟳ 49
    mapping(address owner => mapping(uint256 id => uint256 balance)) public balanceOf;
18

                            
                        
19
    mapping(address owner => mapping(address spender => mapping(uint256 id => uint256 amount))) public allowance;
20

                            
                        
21
    /*//////////////////////////////////////////////////////////////
22
                              ERC6909 LOGIC
23
    //////////////////////////////////////////////////////////////*/
24

                            
                        
25
    function transfer(address receiver, uint256 id, uint256 amount) public virtual returns (bool) {
26
        balanceOf[msg.sender][id] -= amount;
27

                            
                        
28
        balanceOf[receiver][id] += amount;
29

                            
                        
30
        emit Transfer(msg.sender, msg.sender, receiver, id, amount);
31

                            
                        
32
        return true;
33
    }
34

                            
                        
35
    function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public virtual returns (bool) {
36
        if (msg.sender != sender && !isOperator[sender][msg.sender]) {
37
            uint256 allowed = allowance[sender][msg.sender][id];
38
            if (allowed != type(uint256).max) allowance[sender][msg.sender][id] = allowed - amount;
39
        }
40

                            
                        
41
        balanceOf[sender][id] -= amount;
42

                            
                        
43
        balanceOf[receiver][id] += amount;
44

                            
                        
45
        emit Transfer(msg.sender, sender, receiver, id, amount);
46

                            
                        
47
        return true;
48
    }
49

                            
                        
50
    function approve(address spender, uint256 id, uint256 amount) public virtual returns (bool) {
51
        allowance[msg.sender][spender][id] = amount;
52

                            
                        
53
        emit Approval(msg.sender, spender, id, amount);
54

                            
                        
55
        return true;
56
    }
57

                            
                        
58
    function setOperator(address operator, bool approved) public virtual returns (bool) {
59
        isOperator[msg.sender][operator] = approved;
60

                            
                        
61
        emit OperatorSet(msg.sender, operator, approved);
62

                            
                        
63
        return true;
64
    }
65

                            
                        
66
    /*//////////////////////////////////////////////////////////////
67
                              ERC165 LOGIC
68
    //////////////////////////////////////////////////////////////*/
69

                            
                        
70
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
71
        return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165
72
            || interfaceId == 0x0f632fb3; // ERC165 Interface ID for ERC6909
73
    }
74

                            
                        
75
    /*//////////////////////////////////////////////////////////////
76
                        INTERNAL MINT/BURN LOGIC
77
    //////////////////////////////////////////////////////////////*/
78

                            
                        
79
    function _mint(address receiver, uint256 id, uint256 amount) internal virtual {
80
√ 5
⟳ 5
        balanceOf[receiver][id] += amount;
81

                            
                        
82
√ 5
⟳ 5
        emit Transfer(msg.sender, address(0), receiver, id, amount);
83
    }
84

                            
                        
85
    function _burn(address sender, uint256 id, uint256 amount) internal virtual {
86
√ 5
⟳ 5
        balanceOf[sender][id] -= amount;
87

                            
                        
88
√ 5
⟳ 5
        emit Transfer(msg.sender, sender, address(0), id, amount);
89
    }
90
}
91

                            
                        

Lines covered: 6 / 6 (100.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {ERC6909} from "./ERC6909.sol";
5

                            
                        
6
/// @notice ERC6909Claims inherits ERC6909 and implements an internal burnFrom function
7
abstract contract ERC6909Claims is ERC6909 {
8
    /// @notice Burn `amount` tokens of token type `id` from `from`.
9
    /// @dev if sender is not `from` they must be an operator or have sufficient allowance.
10
    /// @param from The address to burn tokens from.
11
    /// @param id The currency to burn.
12
    /// @param amount The amount to burn.
13
    function _burnFrom(address from, uint256 id, uint256 amount) internal {
14
√ 1
⟳ 1
        address sender = msg.sender;
15
√ 9
⟳ 9
        if (from != sender && !isOperator[from][sender]) {
16
√ 2
⟳ 2
            uint256 senderAllowance = allowance[from][sender][id];
17
√ 1
⟳ 1
            if (senderAllowance != type(uint256).max) {
18
√ 3
⟳ 3
                allowance[from][sender][id] = senderAllowance - amount;
19
            }
20
        }
21
√ 4
⟳ 4
        _burn(from, id, amount);
22
    }
23
}
24

                            
                        

Lines covered: 16 / 30 (53.3%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {IExtsload} from "./interfaces/IExtsload.sol";
5

                            
                        
6
/// @notice Enables public storage access for efficient state retrieval by external contracts.
7
/// https://eips.ethereum.org/EIPS/eip-2330#rationale
8
abstract contract Extsload is IExtsload {
9
    /// @inheritdoc IExtsload
10
√ 1
⟳ 1
    function extsload(bytes32 slot) external view returns (bytes32) {
11
        assembly ("memory-safe") {
12
√ 2
⟳ 2
            mstore(0, sload(slot))
13
√ 2
⟳ 2
            return(0, 0x20)
14
        }
15
    }
16

                            
                        
17
    /// @inheritdoc IExtsload
18
√ 1
⟳ 1
    function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory) {
19
        assembly ("memory-safe") {
20
√ 1
⟳ 1
            let memptr := mload(0x40)
21
√ 1
⟳ 1
            let start := memptr
22
            // A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas.
23
√ 2
⟳ 2
            let length := shl(5, nSlots)
24
            // The abi offset of dynamic array in the returndata is 32.
25
√ 2
⟳ 2
            mstore(memptr, 0x20)
26
            // Store the length of the array returned
27
√ 3
⟳ 3
            mstore(add(memptr, 0x20), nSlots)
28
            // update memptr to the first location to hold a result
29
√ 2
⟳ 2
            memptr := add(memptr, 0x40)
30
√ 2
⟳ 2
            let end := add(memptr, length)
31
            for {} 1 {} {
32
√ 4
⟳ 4
                mstore(memptr, sload(startSlot))
33
√ 4
⟳ 4
                memptr := add(memptr, 0x20)
34
√ 4
⟳ 4
                startSlot := add(startSlot, 1)
35
√ 4
⟳ 4
                if iszero(lt(memptr, end)) { break }
36
            }
37
√ 3
⟳ 3
            return(start, sub(end, start))
38
        }
39
    }
40

                            
                        
41
    /// @inheritdoc IExtsload
42
    function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
43
        assembly ("memory-safe") {
44
            let memptr := mload(0x40)
45
            let start := memptr
46
            // for abi encoding the response - the array will be found at 0x20
47
            mstore(memptr, 0x20)
48
            // next we store the length of the return array
49
            mstore(add(memptr, 0x20), slots.length)
50
            // update memptr to the first location to hold an array entry
51
            memptr := add(memptr, 0x40)
52
            // A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas.
53
            let end := add(memptr, shl(5, slots.length))
54
            let calldataptr := slots.offset
55
            for {} 1 {} {
56
                mstore(memptr, sload(calldataload(calldataptr)))
57
                memptr := add(memptr, 0x20)
58
                calldataptr := add(calldataptr, 0x20)
59
                if iszero(lt(memptr, end)) { break }
60
            }
61
            return(start, sub(end, start))
62
        }
63
    }
64
}
65

                            
                        

Lines covered: 3 / 17 (17.6%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {IExttload} from "./interfaces/IExttload.sol";
5

                            
                        
6
/// @notice Enables public transient storage access for efficient state retrieval by external contracts.
7
/// https://eips.ethereum.org/EIPS/eip-2330#rationale
8
abstract contract Exttload is IExttload {
9
    /// @inheritdoc IExttload
10
√ 1
⟳ 1
    function exttload(bytes32 slot) external view returns (bytes32) {
11
        assembly ("memory-safe") {
12
√ 2
⟳ 2
            mstore(0, tload(slot))
13
√ 2
⟳ 2
            return(0, 0x20)
14
        }
15
    }
16

                            
                        
17
    /// @inheritdoc IExttload
18
    function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
19
        assembly ("memory-safe") {
20
            let memptr := mload(0x40)
21
            let start := memptr
22
            // for abi encoding the response - the array will be found at 0x20
23
            mstore(memptr, 0x20)
24
            // next we store the length of the return array
25
            mstore(add(memptr, 0x20), slots.length)
26
            // update memptr to the first location to hold an array entry
27
            memptr := add(memptr, 0x40)
28
            // A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas.
29
            let end := add(memptr, shl(5, slots.length))
30
            let calldataptr := slots.offset
31
            for {} 1 {} {
32
                mstore(memptr, tload(calldataload(calldataptr)))
33
                memptr := add(memptr, 0x20)
34
                calldataptr := add(calldataptr, 0x20)
35
                if iszero(lt(memptr, end)) { break }
36
            }
37
            return(start, sub(end, start))
38
        }
39
    }
40
}
41

                            
                        

Lines covered: 3 / 4 (75.0%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {CustomRevert} from "./libraries/CustomRevert.sol";
5

                            
                        
6
/// @title Prevents delegatecall to a contract
7
/// @notice Base contract that provides a modifier for preventing delegatecall to methods in a child contract
8
abstract contract NoDelegateCall {
9
    using CustomRevert for bytes4;
10

                            
                        
11
    error DelegateCallNotAllowed();
12

                            
                        
13
    /// @dev The original address of this contract
14
    address private immutable original;
15

                            
                        
16
    constructor() {
17
        // Immutables are computed in the init code of the contract, and then inlined into the deployed bytecode.
18
        // In other words, this variable won't change when it's checked at runtime.
19
√ 1
        original = address(this);
20
    }
21

                            
                        
22
    /// @dev Private method is used instead of inlining into modifier because modifiers are copied into each method,
23
    ///     and the use of immutable means the address bytes are copied in every place the modifier is used.
24
    function checkNotDelegateCall() private view {
25
√ 2
⟳ 2
        if (address(this) != original) DelegateCallNotAllowed.selector.revertWith();
26
    }
27

                            
                        
28
    /// @notice Prevents delegatecall into the modified method
29
    modifier noDelegateCall() {
30
√ 4
⟳ 4
        checkNotDelegateCall();
31
        _;
32
    }
33
}
34

                            
                        

Lines covered: 107 / 117 (91.5%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Hooks} from "./libraries/Hooks.sol";
5
import {Pool} from "./libraries/Pool.sol";
6
import {SafeCast} from "./libraries/SafeCast.sol";
7
import {Position} from "./libraries/Position.sol";
8
import {LPFeeLibrary} from "./libraries/LPFeeLibrary.sol";
9
import {Currency, CurrencyLibrary} from "./types/Currency.sol";
10
import {PoolKey} from "./types/PoolKey.sol";
11
import {TickMath} from "./libraries/TickMath.sol";
12
import {NoDelegateCall} from "./NoDelegateCall.sol";
13
import {IHooks} from "./interfaces/IHooks.sol";
14
import {IPoolManager} from "./interfaces/IPoolManager.sol";
15
import {IUnlockCallback} from "./interfaces/callback/IUnlockCallback.sol";
16
import {ProtocolFees} from "./ProtocolFees.sol";
17
import {ERC6909Claims} from "./ERC6909Claims.sol";
18
import {PoolId, PoolIdLibrary} from "./types/PoolId.sol";
19
import {BalanceDelta, BalanceDeltaLibrary} from "./types/BalanceDelta.sol";
20
import {BeforeSwapDelta} from "./types/BeforeSwapDelta.sol";
21
import {Lock} from "./libraries/Lock.sol";
22
import {CurrencyDelta} from "./libraries/CurrencyDelta.sol";
23
import {NonZeroDeltaCount} from "./libraries/NonZeroDeltaCount.sol";
24
import {CurrencyReserves} from "./libraries/CurrencyReserves.sol";
25
import {Extsload} from "./Extsload.sol";
26
import {Exttload} from "./Exttload.sol";
27
import {CustomRevert} from "./libraries/CustomRevert.sol";
28

                            
                        
29
//  4
30
//   44
31
//     444
32
//       444                   4444
33
//        4444            4444     4444
34
//          4444          4444444    4444                           4
35
//            4444        44444444     4444                         4
36
//             44444       4444444       4444444444444444       444444
37
//           4   44444     44444444       444444444444444444444    4444
38
//            4    44444    4444444         4444444444444444444444  44444
39
//             4     444444  4444444         44444444444444444444444 44  4
40
//              44     44444   444444          444444444444444444444 4     4
41
//               44      44444   44444           4444444444444444444 4 44
42
//                44       4444     44             444444444444444     444
43
//                444     4444                        4444444
44
//               4444444444444                     44                      4
45
//              44444444444                        444444     444444444    44
46
//             444444           4444               4444     4444444444      44
47
//             4444           44    44              4      44444444444
48
//            44444          444444444                   444444444444    4444
49
//            44444          44444444                  4444  44444444    444444
50
//            44444                                  4444   444444444    44444444
51
//           44444                                 4444     44444444    4444444444
52
//          44444                                4444      444444444   444444444444
53
//         44444                               4444        44444444    444444444444
54
//       4444444                             4444          44444444         4444444
55
//      4444444                            44444          44444444          4444444
56
//     44444444                           44444444444444444444444444444        4444
57
//   4444444444                           44444444444444444444444444444         444
58
//  444444444444                         444444444444444444444444444444   444   444
59
//  44444444444444                                      444444444         44444
60
// 44444  44444444444         444                       44444444         444444
61
// 44444  4444444444      4444444444      444444        44444444    444444444444
62
//  444444444444444      4444  444444    4444444       44444444     444444444444
63
//  444444444444444     444    444444     444444       44444444      44444444444
64
//   4444444444444     4444   444444        4444                      4444444444
65
//    444444444444      4     44444         4444                       444444444
66
//     44444444444           444444         444                        44444444
67
//      44444444            444444         4444                         4444444
68
//                          44444          444                          44444
69
//                          44444         444      4                    4444
70
//                          44444        444      44                   444
71
//                          44444       444      4444
72
//                           444444  44444        444
73
//                             444444444           444
74
//                                                  44444   444
75
//                                                      444
76

                            
                        
77
/// @title PoolManager
78
/// @notice Holds the state for all pools
79
contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims, Extsload, Exttload {
80
    using PoolIdLibrary for PoolKey;
81
    using SafeCast for *;
82
    using Pool for *;
83
    using Hooks for IHooks;
84
    using Position for mapping(bytes32 => Position.Info);
85
    using CurrencyDelta for Currency;
86
    using LPFeeLibrary for uint24;
87
    using CurrencyReserves for Currency;
88
    using CustomRevert for bytes4;
89

                            
                        
90
    /// @inheritdoc IPoolManager
91
    int24 public constant MAX_TICK_SPACING = TickMath.MAX_TICK_SPACING;
92

                            
                        
93
    /// @inheritdoc IPoolManager
94
√ 4
⟳ 4
    int24 public constant MIN_TICK_SPACING = TickMath.MIN_TICK_SPACING;
95

                            
                        
96
    mapping(PoolId id => Pool.State) internal _pools;
97

                            
                        
98
√ 2
    constructor(uint256 controllerGasLimit) ProtocolFees(controllerGasLimit) {}
99

                            
                        
100
    /// @notice This will revert if the contract is locked
101
    modifier onlyWhenUnlocked() {
102
        if (!Lock.isUnlocked()) ManagerLocked.selector.revertWith();
103
√ 2
⟳ 2
        _;
104
    }
105

                            
                        
106
    /// @inheritdoc IPoolManager
107
√ 1
⟳ 1
    function unlock(bytes calldata data) external override returns (bytes memory result) {
108
        if (Lock.isUnlocked()) AlreadyUnlocked.selector.revertWith();
109

                            
                        
110
√ 1
⟳ 1
        Lock.unlock();
111

                            
                        
112
        // the caller does everything in this callback, including paying what they owe via calls to settle
113
√ 6
⟳ 6
        result = IUnlockCallback(msg.sender).unlockCallback(data);
114

                            
                        
115
√ 1
⟳ 2
        if (NonZeroDeltaCount.read() != 0) CurrencyNotSettled.selector.revertWith();
116
√ 1
⟳ 1
        Lock.lock();
117
    }
118

                            
                        
119
    /// @inheritdoc IPoolManager
120
    function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData)
121
        external
122
        noDelegateCall
123
√ 1
⟳ 1
        returns (int24 tick)
124
    {
125
        // see TickBitmap.sol for overflow conditions that can arise from tick spacing being too large
126
√ 4
⟳ 10
        if (key.tickSpacing > MAX_TICK_SPACING) TickSpacingTooLarge.selector.revertWith(key.tickSpacing);
127
√ 1
⟳ 7
        if (key.tickSpacing < MIN_TICK_SPACING) TickSpacingTooSmall.selector.revertWith(key.tickSpacing);
128
√ 6
⟳ 6
        if (key.currency0 >= key.currency1) {
129
            CurrenciesOutOfOrderOrEqual.selector.revertWith(
130
                Currency.unwrap(key.currency0), Currency.unwrap(key.currency1)
131
            );
132
        }
133
√ 2
⟳ 8
        if (!key.hooks.isValidHookAddress(key.fee)) Hooks.HookAddressNotValid.selector.revertWith(address(key.hooks));
134

                            
                        
135
√ 2
⟳ 2
        uint24 lpFee = key.fee.getInitialLPFee();
136

                            
                        
137
√ 8
⟳ 8
        key.hooks.beforeInitialize(key, sqrtPriceX96, hookData);
138

                            
                        
139
        PoolId id = key.toId();
140
√ 3
⟳ 3
        (, uint24 protocolFee) = _fetchProtocolFee(key);
141

                            
                        
142
√ 3
⟳ 3
        tick = _pools[id].initialize(sqrtPriceX96, protocolFee, lpFee);
143

                            
                        
144
√ 8
⟳ 8
        key.hooks.afterInitialize(key, sqrtPriceX96, tick, hookData);
145

                            
                        
146
        // emit all details of a pool key. poolkeys are not saved in storage and must always be provided by the caller
147
        // the key's fee may be a static fee or a sentinel to denote a dynamic fee.
148
√ 6
⟳ 6
        emit Initialize(id, key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks);
149
    }
150

                            
                        
151
    /// @inheritdoc IPoolManager
152
    function modifyLiquidity(
153
        PoolKey memory key,
154
        IPoolManager.ModifyLiquidityParams memory params,
155
        bytes calldata hookData
156
√ 2
⟳ 2
    ) external onlyWhenUnlocked noDelegateCall returns (BalanceDelta callerDelta, BalanceDelta feesAccrued) {
157
√ 1
⟳ 1
        PoolId id = key.toId();
158
        Pool.State storage pool = _getPool(id);
159
√ 1
⟳ 1
        pool.checkPoolInitialized();
160

                            
                        
161
√ 8
⟳ 8
        key.hooks.beforeModifyLiquidity(key, params, hookData);
162

                            
                        
163
√ 1
⟳ 1
        BalanceDelta principalDelta;
164
√ 2
⟳ 2
        (principalDelta, feesAccrued) = pool.modifyLiquidity(
165
            Pool.ModifyLiquidityParams({
166
√ 1
⟳ 1
                owner: msg.sender,
167
√ 1
⟳ 1
                tickLower: params.tickLower,
168
√ 1
⟳ 1
                tickUpper: params.tickUpper,
169
√ 1
⟳ 1
                liquidityDelta: params.liquidityDelta.toInt128(),
170
√ 5
⟳ 5
                tickSpacing: key.tickSpacing,
171
√ 3
⟳ 3
                salt: params.salt
172
            })
173
        );
174

                            
                        
175
        // fee delta and principal delta are both accrued to the caller
176
√ 4
⟳ 4
        callerDelta = principalDelta + feesAccrued;
177

                            
                        
178
        // event is emitted before the afterModifyLiquidity call to ensure events are always emitted in order
179
√ 5
⟳ 5
        emit ModifyLiquidity(id, msg.sender, params.tickLower, params.tickUpper, params.liquidityDelta);
180

                            
                        
181
√ 2
⟳ 2
        BalanceDelta hookDelta;
182
√ 9
⟳ 9
        (callerDelta, hookDelta) = key.hooks.afterModifyLiquidity(key, params, callerDelta, hookData);
183

                            
                        
184
        // if the hook doesnt have the flag to be able to return deltas, hookDelta will always be 0
185
        if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks));
186

                            
                        
187
√ 4
⟳ 4
        _accountPoolBalanceDelta(key, callerDelta, msg.sender);
188
    }
189

                            
                        
190
    /// @inheritdoc IPoolManager
191
    function swap(PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData)
192
        external
193
        onlyWhenUnlocked
194
        noDelegateCall
195
√ 1
⟳ 1
        returns (BalanceDelta swapDelta)
196
    {
197
√ 2
⟳ 3
        if (params.amountSpecified == 0) SwapAmountCannotBeZero.selector.revertWith();
198
√ 1
⟳ 1
        PoolId id = key.toId();
199
        Pool.State storage pool = _getPool(id);
200
√ 1
⟳ 1
        pool.checkPoolInitialized();
201

                            
                        
202
√ 6
⟳ 6
        BeforeSwapDelta beforeSwapDelta;
203
        {
204
            int256 amountToSwap;
205
            uint24 lpFeeOverride;
206
√ 8
⟳ 8
            (amountToSwap, beforeSwapDelta, lpFeeOverride) = key.hooks.beforeSwap(key, params, hookData);
207

                            
                        
208
            // execute swap, account protocol fees, and emit swap event
209
            // _swap is needed to avoid stack too deep error
210
√ 2
⟳ 2
            swapDelta = _swap(
211
√ 1
⟳ 1
                pool,
212
√ 1
⟳ 1
                id,
213
                Pool.SwapParams({
214
√ 1
⟳ 1
                    tickSpacing: key.tickSpacing,
215
√ 1
⟳ 1
                    zeroForOne: params.zeroForOne,
216
√ 1
⟳ 1
                    amountSpecified: amountToSwap,
217
√ 1
⟳ 1
                    sqrtPriceLimitX96: params.sqrtPriceLimitX96,
218
√ 1
⟳ 1
                    lpFeeOverride: lpFeeOverride
219
                }),
220
√ 4
⟳ 4
                params.zeroForOne ? key.currency0 : key.currency1 // input token
221
            );
222
        }
223

                            
                        
224
√ 2
⟳ 2
        BalanceDelta hookDelta;
225
√ 9
⟳ 9
        (swapDelta, hookDelta) = key.hooks.afterSwap(key, params, swapDelta, hookData, beforeSwapDelta);
226

                            
                        
227
        // if the hook doesnt have the flag to be able to return deltas, hookDelta will always be 0
228
        if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks));
229

                            
                        
230
√ 4
⟳ 4
        _accountPoolBalanceDelta(key, swapDelta, msg.sender);
231
    }
232

                            
                        
233
    /// @notice Internal swap function to execute a swap, take protocol fees on input token, and emit the swap event
234
    function _swap(Pool.State storage pool, PoolId id, Pool.SwapParams memory params, Currency inputCurrency)
235
        internal
236
√ 5
⟳ 5
        returns (BalanceDelta)
237
    {
238
√ 2
⟳ 2
        (BalanceDelta delta, uint256 feeForProtocol, uint24 swapFee, Pool.SwapState memory state) = pool.swap(params);
239

                            
                        
240
        // the fee is on the input currency
241
√ 3
⟳ 3
        if (feeForProtocol > 0) _updateProtocolFees(inputCurrency, feeForProtocol);
242

                            
                        
243
        // event is emitted before the afterSwap call to ensure events are always emitted in order
244
        emit Swap(
245
√ 20
⟳ 20
            id, msg.sender, delta.amount0(), delta.amount1(), state.sqrtPriceX96, state.liquidity, state.tick, swapFee
246
        );
247

                            
                        
248
√ 2
⟳ 2
        return delta;
249
    }
250

                            
                        
251
    /// @inheritdoc IPoolManager
252
    function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData)
253
        external
254
        onlyWhenUnlocked
255
        noDelegateCall
256
√ 1
⟳ 1
        returns (BalanceDelta delta)
257
    {
258
√ 2
⟳ 2
        Pool.State storage pool = _getPool(key.toId());
259
√ 1
⟳ 1
        pool.checkPoolInitialized();
260

                            
                        
261
√ 9
⟳ 9
        key.hooks.beforeDonate(key, amount0, amount1, hookData);
262

                            
                        
263
√ 3
⟳ 3
        delta = pool.donate(amount0, amount1);
264

                            
                        
265
√ 4
⟳ 4
        _accountPoolBalanceDelta(key, delta, msg.sender);
266

                            
                        
267
√ 9
⟳ 9
        key.hooks.afterDonate(key, amount0, amount1, hookData);
268
    }
269

                            
                        
270
    /// @inheritdoc IPoolManager
271
    function sync(Currency currency) external {
272
√ 1
⟳ 1
        CurrencyReserves.requireNotSynced();
273
√ 3
⟳ 3
        if (currency.isNative()) return;
274
√ 2
⟳ 2
        uint256 balance = currency.balanceOfSelf();
275
√ 3
⟳ 3
        CurrencyReserves.syncCurrencyAndReserves(currency, balance);
276
    }
277

                            
                        
278
    /// @inheritdoc IPoolManager
279
    function take(Currency currency, address to, uint256 amount) external onlyWhenUnlocked {
280
        unchecked {
281
            // negation must be safe as amount is not negative
282
√ 4
⟳ 4
            _accountDelta(currency, -(amount.toInt128()), msg.sender);
283
√ 6
⟳ 6
            currency.transfer(to, amount);
284
        }
285
    }
286

                            
                        
287
    /// @inheritdoc IPoolManager
288
√ 1
⟳ 1
    function settle() external payable onlyWhenUnlocked returns (uint256 paid) {
289
√ 2
⟳ 2
        return _settle(msg.sender);
290
    }
291

                            
                        
292
    /// @inheritdoc IPoolManager
293
√ 1
⟳ 1
    function settleFor(address recipient) external payable onlyWhenUnlocked returns (uint256 paid) {
294
√ 2
⟳ 2
        return _settle(recipient);
295
    }
296

                            
                        
297
    /// @inheritdoc IPoolManager
298
    function clear(Currency currency, uint256 amount) external onlyWhenUnlocked {
299
√ 5
⟳ 5
        int256 current = currency.getDelta(msg.sender);
300
        // Because input is `uint256`, only positive amounts can be cleared.
301
√ 1
⟳ 1
        int128 amountDelta = amount.toInt128();
302
√ 2
⟳ 3
        if (amountDelta != current) MustClearExactPositiveDelta.selector.revertWith();
303
√ 4
⟳ 4
        _accountDelta(currency, -(amountDelta), msg.sender);
304
    }
305

                            
                        
306
    /// @inheritdoc IPoolManager
307
    function mint(address to, uint256 id, uint256 amount) external onlyWhenUnlocked {
308
        unchecked {
309
√ 2
⟳ 2
            Currency currency = CurrencyLibrary.fromId(id);
310
            // negation must be safe as amount is not negative
311
√ 1
⟳ 1
            _accountDelta(currency, -(amount.toInt128()), msg.sender);
312
√ 6
⟳ 6
            _mint(to, currency.toId(), amount);
313
        }
314
    }
315

                            
                        
316
    /// @inheritdoc IPoolManager
317
    function burn(address from, uint256 id, uint256 amount) external onlyWhenUnlocked {
318
√ 2
⟳ 2
        Currency currency = CurrencyLibrary.fromId(id);
319
√ 1
⟳ 1
        _accountDelta(currency, amount.toInt128(), msg.sender);
320
√ 6
⟳ 6
        _burnFrom(from, currency.toId(), amount);
321
    }
322

                            
                        
323
    /// @inheritdoc IPoolManager
324
    function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external {
325
⟳ 4
        if (!key.fee.isDynamicFee() || msg.sender != address(key.hooks)) {
326
⟳ 1
            UnauthorizedDynamicLPFeeUpdate.selector.revertWith();
327
        }
328
        newDynamicLPFee.validate();
329
        PoolId id = key.toId();
330
        _pools[id].setLPFee(newDynamicLPFee);
331
    }
332

                            
                        
333
√ 1
⟳ 1
    function _settle(address recipient) internal returns (uint256 paid) {
334
        Currency currency = CurrencyReserves.getSyncedCurrency();
335
        // If not previously synced, expects native currency to be settled because CurrencyLibrary.NATIVE == address(0)
336
√ 3
⟳ 3
        if (currency.isNative()) {
337
√ 1
⟳ 1
            paid = msg.value;
338
        } else {
339
√ 1
⟳ 2
            if (msg.value > 0) NonZeroNativeValue.selector.revertWith();
340
            // Reserves are guaranteed to be set, because currency and reserves are always set together
341
√ 1
⟳ 1
            uint256 reservesBefore = CurrencyReserves.getSyncedReserves();
342
√ 4
⟳ 4
            uint256 reservesNow = currency.balanceOfSelf();
343
√ 1
⟳ 1
            paid = reservesNow - reservesBefore;
344
√ 1
⟳ 1
            CurrencyReserves.resetCurrency();
345
        }
346
√ 4
⟳ 4
        _accountDelta(currency, paid.toInt128(), recipient);
347
    }
348

                            
                        
349
    /// @notice Adds a balance delta in a currency for a target address
350
    function _accountDelta(Currency currency, int128 delta, address target) internal {
351
√ 2
⟳ 2
        if (delta == 0) return;
352

                            
                        
353
√ 8
⟳ 8
        (int256 previous, int256 next) = currency.applyDelta(target, delta);
354

                            
                        
355
√ 2
⟳ 2
        if (next == 0) {
356
√ 1
⟳ 1
            NonZeroDeltaCount.decrement();
357
√ 2
⟳ 4
        } else if (previous == 0) {
358
√ 1
⟳ 2
            NonZeroDeltaCount.increment();
359
        }
360
    }
361

                            
                        
362
    /// @notice Accounts the deltas of 2 currencies to a target address
363
    function _accountPoolBalanceDelta(PoolKey memory key, BalanceDelta delta, address target) internal {
364
√ 7
⟳ 7
        _accountDelta(key.currency0, delta.amount0(), target);
365
√ 2
⟳ 2
        _accountDelta(key.currency1, delta.amount1(), target);
366
    }
367

                            
                        
368
    /// @notice Implementation of the _getPool function defined in ProtocolFees
369
√ 2
⟳ 2
    function _getPool(PoolId id) internal view override returns (Pool.State storage) {
370
√ 4
⟳ 4
        return _pools[id];
371
    }
372
}
373

                            
                        

Lines covered: 30 / 30 (100.0%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {Currency} from "./types/Currency.sol";
5
import {IProtocolFeeController} from "./interfaces/IProtocolFeeController.sol";
6
import {IProtocolFees} from "./interfaces/IProtocolFees.sol";
7
import {PoolKey} from "./types/PoolKey.sol";
8
import {ProtocolFeeLibrary} from "./libraries/ProtocolFeeLibrary.sol";
9
import {Owned} from "solmate/auth/Owned.sol";
10
import {PoolId, PoolIdLibrary} from "./types/PoolId.sol";
11
import {Pool} from "./libraries/Pool.sol";
12
import {CustomRevert} from "./libraries/CustomRevert.sol";
13

                            
                        
14
/// @notice Contract handling the setting and accrual of protocol fees
15
abstract contract ProtocolFees is IProtocolFees, Owned {
16
    using ProtocolFeeLibrary for uint24;
17
    using PoolIdLibrary for PoolKey;
18
    using Pool for Pool.State;
19
    using CustomRevert for bytes4;
20

                            
                        
21
    /// @inheritdoc IProtocolFees
22
√ 27
⟳ 27
    mapping(Currency currency => uint256 amount) public protocolFeesAccrued;
23

                            
                        
24
    /// @inheritdoc IProtocolFees
25
√ 15
⟳ 15
    IProtocolFeeController public protocolFeeController;
26

                            
                        
27
    uint256 private immutable controllerGasLimit;
28

                            
                        
29
√ 3
    constructor(uint256 _controllerGasLimit) Owned(msg.sender) {
30
√ 2
        controllerGasLimit = _controllerGasLimit;
31
    }
32

                            
                        
33
    /// @inheritdoc IProtocolFees
34
    function setProtocolFeeController(IProtocolFeeController controller) external onlyOwner {
35
√ 1
⟳ 1
        protocolFeeController = controller;
36
√ 5
⟳ 5
        emit ProtocolFeeControllerUpdated(address(controller));
37
    }
38

                            
                        
39
    /// @inheritdoc IProtocolFees
40
    function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external {
41
√ 5
⟳ 5
        if (msg.sender != address(protocolFeeController)) InvalidCaller.selector.revertWith();
42
⟳ 1
        if (!newProtocolFee.isValidProtocolFee()) ProtocolFeeTooLarge.selector.revertWith(newProtocolFee);
43
        PoolId id = key.toId();
44
√ 2
⟳ 2
        _getPool(id).setProtocolFee(newProtocolFee);
45
√ 2
⟳ 2
        emit ProtocolFeeUpdated(id, newProtocolFee);
46
    }
47

                            
                        
48
    /// @inheritdoc IProtocolFees
49
    function collectProtocolFees(address recipient, Currency currency, uint256 amount)
50
        external
51
√ 2
⟳ 2
        returns (uint256 amountCollected)
52
    {
53
√ 5
⟳ 5
        if (msg.sender != address(protocolFeeController)) InvalidCaller.selector.revertWith();
54

                            
                        
55
√ 4
⟳ 4
        amountCollected = (amount == 0) ? protocolFeesAccrued[currency] : amount;
56
√ 1
⟳ 1
        protocolFeesAccrued[currency] -= amountCollected;
57
√ 6
⟳ 6
        currency.transfer(recipient, amountCollected);
58
    }
59

                            
                        
60
    /// @dev abstract internal function to allow the ProtocolFees contract to access pool state
61
    /// @dev this is overriden in PoolManager.sol to give access to the _pools mapping
62
    function _getPool(PoolId id) internal virtual returns (Pool.State storage);
63

                            
                        
64
    /// @notice Fetch the protocol fees for a given pool, returning false if the call fails or the returned fees are invalid.
65
    /// @dev to prevent an invalid protocol fee controller from blocking pools from being initialized
66
    ///      the success of this function is NOT checked on initialize and if the call fails, the protocol fees are set to 0.
67
    /// @dev the success of this function must be checked when called in setProtocolFee
68
√ 4
⟳ 4
    function _fetchProtocolFee(PoolKey memory key) internal returns (bool success, uint24 protocolFee) {
69
√ 3
⟳ 3
        if (address(protocolFeeController) != address(0)) {
70
            // note that EIP-150 mandates that calls requesting more than 63/64ths of remaining gas
71
            // will be allotted no more than this amount, so controllerGasLimit must be set with this
72
            // in mind.
73
√ 2
⟳ 2
            if (gasleft() < controllerGasLimit) ProtocolFeeCannotBeFetched.selector.revertWith();
74

                            
                        
75
√ 4
⟳ 4
            uint256 gasLimit = controllerGasLimit;
76
√ 5
⟳ 5
            address toAddress = address(protocolFeeController);
77

                            
                        
78
√ 2
⟳ 2
            bytes memory data = abi.encodeCall(IProtocolFeeController.protocolFeeForPool, (key));
79
            uint256 returnData;
80
            assembly ("memory-safe") {
81
√ 5
⟳ 5
                success := call(gasLimit, toAddress, 0, add(data, 0x20), mload(data), 0, 0)
82

                            
                        
83
                // success if return data size is 32 bytes
84
                // only load the return value if it is 32 bytes to prevent gas griefing
85
√ 2
⟳ 2
                success := and(success, eq(returndatasize(), 32))
86

                            
                        
87
                // load the return data if success is true
88
                if success {
89
√ 1
⟳ 1
                    let fmp := mload(0x40)
90
√ 3
⟳ 3
                    returndatacopy(fmp, 0, returndatasize())
91
√ 1
⟳ 1
                    returnData := mload(fmp)
92
√ 2
⟳ 2
                    mstore(fmp, 0)
93
                }
94
            }
95

                            
                        
96
            // Ensure return data does not overflow a uint24 and that the underlying fees are within bounds.
97
√ 3
⟳ 3
            (success, protocolFee) = success && (returnData == uint24(returnData))
98
√ 3
⟳ 3
                && uint24(returnData).isValidProtocolFee() ? (true, uint24(returnData)) : (false, 0);
99
        }
100
    }
101

                            
                        
102
    function _updateProtocolFees(Currency currency, uint256 amount) internal {
103
        unchecked {
104
√ 1
⟳ 1
            protocolFeesAccrued[currency] += amount;
105
        }
106
    }
107
}
108

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @notice Interface for functions to access any storage slot in a contract
5
interface IExtsload {
6
    /// @notice Called by external contracts to access granular pool state
7
    /// @param slot Key of slot to sload
8
    /// @return value The value of the slot as bytes32
9
    function extsload(bytes32 slot) external view returns (bytes32 value);
10

                            
                        
11
    /// @notice Called by external contracts to access granular pool state
12
    /// @param startSlot Key of slot to start sloading from
13
    /// @param nSlots Number of slots to load into return value
14
    /// @return values List of loaded values.
15
    function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory values);
16

                            
                        
17
    /// @notice Called by external contracts to access sparse pool state
18
    /// @param slots List of slots to SLOAD from.
19
    /// @return values List of loaded values.
20
    function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory values);
21
}
22

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.24;
3

                            
                        
4
/// @notice Interface for functions to access any transient storage slot in a contract
5
interface IExttload {
6
    /// @notice Called by external contracts to access transient storage of the contract
7
    /// @param slot Key of slot to tload
8
    /// @return value The value of the slot as bytes32
9
    function exttload(bytes32 slot) external view returns (bytes32 value);
10

                            
                        
11
    /// @notice Called by external contracts to access sparse transient pool state
12
    /// @param slots List of slots to tload
13
    /// @return values List of loaded values
14
    function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values);
15
}
16

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {PoolKey} from "../types/PoolKey.sol";
5
import {BalanceDelta} from "../types/BalanceDelta.sol";
6
import {IPoolManager} from "./IPoolManager.sol";
7
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
8

                            
                        
9
/// @notice The PoolManager contract decides whether to invoke specific hooks by inspecting the leading bits
10
/// of the hooks contract address. For example, a 1 bit in the first bit of the address will
11
/// cause the 'before swap' hook to be invoked. See the Hooks library for the full spec.
12
/// @dev Should only be callable by the v4 PoolManager.
13
interface IHooks {
14
    /// @notice The hook called before the state of a pool is initialized
15
    /// @param sender The initial msg.sender for the initialize call
16
    /// @param key The key for the pool being initialized
17
    /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96
18
    /// @param hookData Arbitrary data handed into the PoolManager by the initializer to be be passed on to the hook
19
    /// @return bytes4 The function selector for the hook
20
    function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, bytes calldata hookData)
21
        external
22
        returns (bytes4);
23

                            
                        
24
    /// @notice The hook called after the state of a pool is initialized
25
    /// @param sender The initial msg.sender for the initialize call
26
    /// @param key The key for the pool being initialized
27
    /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96
28
    /// @param tick The current tick after the state of a pool is initialized
29
    /// @param hookData Arbitrary data handed into the PoolManager by the initializer to be be passed on to the hook
30
    /// @return bytes4 The function selector for the hook
31
    function afterInitialize(
32
        address sender,
33
        PoolKey calldata key,
34
        uint160 sqrtPriceX96,
35
        int24 tick,
36
        bytes calldata hookData
37
    ) external returns (bytes4);
38

                            
                        
39
    /// @notice The hook called before liquidity is added
40
    /// @param sender The initial msg.sender for the add liquidity call
41
    /// @param key The key for the pool
42
    /// @param params The parameters for adding liquidity
43
    /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook
44
    /// @return bytes4 The function selector for the hook
45
    function beforeAddLiquidity(
46
        address sender,
47
        PoolKey calldata key,
48
        IPoolManager.ModifyLiquidityParams calldata params,
49
        bytes calldata hookData
50
    ) external returns (bytes4);
51

                            
                        
52
    /// @notice The hook called after liquidity is added
53
    /// @param sender The initial msg.sender for the add liquidity call
54
    /// @param key The key for the pool
55
    /// @param params The parameters for adding liquidity
56
    /// @param delta The caller's balance delta after adding liquidity
57
    /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook
58
    /// @return bytes4 The function selector for the hook
59
    /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
60
    function afterAddLiquidity(
61
        address sender,
62
        PoolKey calldata key,
63
        IPoolManager.ModifyLiquidityParams calldata params,
64
        BalanceDelta delta,
65
        bytes calldata hookData
66
    ) external returns (bytes4, BalanceDelta);
67

                            
                        
68
    /// @notice The hook called before liquidity is removed
69
    /// @param sender The initial msg.sender for the remove liquidity call
70
    /// @param key The key for the pool
71
    /// @param params The parameters for removing liquidity
72
    /// @param hookData Arbitrary data handed into the PoolManager by the liquidty provider to be be passed on to the hook
73
    /// @return bytes4 The function selector for the hook
74
    function beforeRemoveLiquidity(
75
        address sender,
76
        PoolKey calldata key,
77
        IPoolManager.ModifyLiquidityParams calldata params,
78
        bytes calldata hookData
79
    ) external returns (bytes4);
80

                            
                        
81
    /// @notice The hook called after liquidity is removed
82
    /// @param sender The initial msg.sender for the remove liquidity call
83
    /// @param key The key for the pool
84
    /// @param params The parameters for removing liquidity
85
    /// @param delta The caller's balance delta after removing liquidity
86
    /// @param hookData Arbitrary data handed into the PoolManager by the liquidty provider to be be passed on to the hook
87
    /// @return bytes4 The function selector for the hook
88
    /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
89
    function afterRemoveLiquidity(
90
        address sender,
91
        PoolKey calldata key,
92
        IPoolManager.ModifyLiquidityParams calldata params,
93
        BalanceDelta delta,
94
        bytes calldata hookData
95
    ) external returns (bytes4, BalanceDelta);
96

                            
                        
97
    /// @notice The hook called before a swap
98
    /// @param sender The initial msg.sender for the swap call
99
    /// @param key The key for the pool
100
    /// @param params The parameters for the swap
101
    /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook
102
    /// @return bytes4 The function selector for the hook
103
    /// @return BeforeSwapDelta The hook's delta in specified and unspecified currencies. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
104
    /// @return uint24 Optionally override the lp fee, only used if three conditions are met: 1. the Pool has a dynamic fee, 2. the value's 2nd highest bit is set (23rd bit, 0x400000), and 3. the value is less than or equal to the maximum fee (1 million)
105
    function beforeSwap(
106
        address sender,
107
        PoolKey calldata key,
108
        IPoolManager.SwapParams calldata params,
109
        bytes calldata hookData
110
    ) external returns (bytes4, BeforeSwapDelta, uint24);
111

                            
                        
112
    /// @notice The hook called after a swap
113
    /// @param sender The initial msg.sender for the swap call
114
    /// @param key The key for the pool
115
    /// @param params The parameters for the swap
116
    /// @param delta The amount owed to the caller (positive) or owed to the pool (negative)
117
    /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook
118
    /// @return bytes4 The function selector for the hook
119
    /// @return int128 The hook's delta in unspecified currency. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
120
    function afterSwap(
121
        address sender,
122
        PoolKey calldata key,
123
        IPoolManager.SwapParams calldata params,
124
        BalanceDelta delta,
125
        bytes calldata hookData
126
    ) external returns (bytes4, int128);
127

                            
                        
128
    /// @notice The hook called before donate
129
    /// @param sender The initial msg.sender for the donate call
130
    /// @param key The key for the pool
131
    /// @param amount0 The amount of token0 being donated
132
    /// @param amount1 The amount of token1 being donated
133
    /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook
134
    /// @return bytes4 The function selector for the hook
135
    function beforeDonate(
136
        address sender,
137
        PoolKey calldata key,
138
        uint256 amount0,
139
        uint256 amount1,
140
        bytes calldata hookData
141
    ) external returns (bytes4);
142

                            
                        
143
    /// @notice The hook called after donate
144
    /// @param sender The initial msg.sender for the donate call
145
    /// @param key The key for the pool
146
    /// @param amount0 The amount of token0 being donated
147
    /// @param amount1 The amount of token1 being donated
148
    /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook
149
    /// @return bytes4 The function selector for the hook
150
    function afterDonate(
151
        address sender,
152
        PoolKey calldata key,
153
        uint256 amount0,
154
        uint256 amount1,
155
        bytes calldata hookData
156
    ) external returns (bytes4);
157
}
158

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Currency} from "../types/Currency.sol";
5
import {PoolKey} from "../types/PoolKey.sol";
6
import {IHooks} from "./IHooks.sol";
7
import {IERC6909Claims} from "./external/IERC6909Claims.sol";
8
import {IProtocolFees} from "./IProtocolFees.sol";
9
import {BalanceDelta} from "../types/BalanceDelta.sol";
10
import {PoolId} from "../types/PoolId.sol";
11
import {IExtsload} from "./IExtsload.sol";
12
import {IExttload} from "./IExttload.sol";
13

                            
                        
14
/// @notice Interface for the PoolManager
15
interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload {
16
    /// @notice Thrown when a currency is not netted out after the contract is unlocked
17
    error CurrencyNotSettled();
18

                            
                        
19
    /// @notice Thrown when trying to interact with a non-initialized pool
20
    error PoolNotInitialized();
21

                            
                        
22
    /// @notice Thrown when unlock is called, but the contract is already unlocked
23
    error AlreadyUnlocked();
24

                            
                        
25
    /// @notice Thrown when a function is called that requires the contract to be unlocked, but it is not
26
    error ManagerLocked();
27

                            
                        
28
    /// @notice Pools are limited to type(int16).max tickSpacing in #initialize, to prevent overflow
29
    error TickSpacingTooLarge(int24 tickSpacing);
30

                            
                        
31
    /// @notice Pools must have a positive non-zero tickSpacing passed to #initialize
32
    error TickSpacingTooSmall(int24 tickSpacing);
33

                            
                        
34
    /// @notice PoolKey must have currencies where address(currency0) < address(currency1)
35
    error CurrenciesOutOfOrderOrEqual(address currency0, address currency1);
36

                            
                        
37
    /// @notice Thrown when a call to updateDynamicLPFee is made by an address that is not the hook,
38
    /// or on a pool that does not have a dynamic swap fee.
39
    error UnauthorizedDynamicLPFeeUpdate();
40

                            
                        
41
    /// @notice Thrown when trying to swap amount of 0
42
    error SwapAmountCannotBeZero();
43

                            
                        
44
    ///@notice Thrown when native currency is passed to a non native settlement
45
    error NonZeroNativeValue();
46

                            
                        
47
    /// @notice Thrown when `clear` is called with an amount that is not exactly equal to the open currency delta.
48
    error MustClearExactPositiveDelta();
49

                            
                        
50
    /// @notice Emitted when a new pool is initialized
51
    /// @param id The abi encoded hash of the pool key struct for the new pool
52
    /// @param currency0 The first currency of the pool by address sort order
53
    /// @param currency1 The second currency of the pool by address sort order
54
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
55
    /// @param tickSpacing The minimum number of ticks between initialized ticks
56
    /// @param hooks The hooks contract address for the pool, or address(0) if none
57
    event Initialize(
58
        PoolId indexed id,
59
        Currency indexed currency0,
60
        Currency indexed currency1,
61
        uint24 fee,
62
        int24 tickSpacing,
63
        IHooks hooks
64
    );
65

                            
                        
66
    /// @notice Emitted when a liquidity position is modified
67
    /// @param id The abi encoded hash of the pool key struct for the pool that was modified
68
    /// @param sender The address that modified the pool
69
    /// @param tickLower The lower tick of the position
70
    /// @param tickUpper The upper tick of the position
71
    /// @param liquidityDelta The amount of liquidity that was added or removed
72
    event ModifyLiquidity(
73
        PoolId indexed id, address indexed sender, int24 tickLower, int24 tickUpper, int256 liquidityDelta
74
    );
75

                            
                        
76
    /// @notice Emitted for swaps between currency0 and currency1
77
    /// @param id The abi encoded hash of the pool key struct for the pool that was modified
78
    /// @param sender The address that initiated the swap call, and that received the callback
79
    /// @param amount0 The delta of the currency0 balance of the pool
80
    /// @param amount1 The delta of the currency1 balance of the pool
81
    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96
82
    /// @param liquidity The liquidity of the pool after the swap
83
    /// @param tick The log base 1.0001 of the price of the pool after the swap
84
    /// @param fee The swap fee in hundredths of a bip
85
    event Swap(
86
        PoolId indexed id,
87
        address indexed sender,
88
        int128 amount0,
89
        int128 amount1,
90
        uint160 sqrtPriceX96,
91
        uint128 liquidity,
92
        int24 tick,
93
        uint24 fee
94
    );
95

                            
                        
96
    /// @return int24 the constant representing the maximum tickSpacing for an initialized pool key
97
    function MAX_TICK_SPACING() external view returns (int24);
98

                            
                        
99
    /// @return int24 the constant representing the minimum tickSpacing for an initialized pool key
100
    function MIN_TICK_SPACING() external view returns (int24);
101

                            
                        
102
    /// @notice All interactions on the contract that account deltas require unlocking. A caller that calls `unlock` must implement
103
    /// `IUnlockCallback(msg.sender).unlockCallback(data)`, where they interact with the remaining functions on this contract.
104
    /// @dev The only functions callable without an unlocking are `initialize` and `updateDynamicLPFee`
105
    /// @param data Any data to pass to the callback, via `IUnlockCallback(msg.sender).unlockCallback(data)`
106
    /// @return The data returned by the call to `IUnlockCallback(msg.sender).unlockCallback(data)`
107
    function unlock(bytes calldata data) external returns (bytes memory);
108

                            
                        
109
    /// @notice Initialize the state for a given pool ID
110
    /// @param key The pool key for the pool to initialize
111
    /// @param sqrtPriceX96 The initial square root price
112
    /// @param hookData The data to pass through to the initialize hooks
113
    /// @return tick The initial tick of the pool
114
    function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData)
115
        external
116
        returns (int24 tick);
117

                            
                        
118
    struct ModifyLiquidityParams {
119
        // the lower and upper tick of the position
120
        int24 tickLower;
121
        int24 tickUpper;
122
        // how to modify the liquidity
123
        int256 liquidityDelta;
124
        // a value to set if you want unique liquidity positions at the same range
125
        bytes32 salt;
126
    }
127

                            
                        
128
    /// @notice Modify the liquidity for the given pool
129
    /// @dev Poke by calling with a zero liquidityDelta
130
    /// @param key The pool to modify liquidity in
131
    /// @param params The parameters for modifying the liquidity
132
    /// @param hookData The data to pass through to the add/removeLiquidity hooks
133
    /// @return callerDelta The balance delta of the caller of modifyLiquidity. This is the total of both principal and fee deltas.
134
    /// @return feeDelta The balance delta of the fees generated in the liquidity range. Returned for informational purposes.
135
    function modifyLiquidity(PoolKey memory key, ModifyLiquidityParams memory params, bytes calldata hookData)
136
        external
137
        returns (BalanceDelta callerDelta, BalanceDelta feeDelta);
138

                            
                        
139
    struct SwapParams {
140
        bool zeroForOne;
141
        int256 amountSpecified;
142
        uint160 sqrtPriceLimitX96;
143
    }
144

                            
                        
145
    /// @notice Swap against the given pool
146
    /// @param key The pool to swap in
147
    /// @param params The parameters for swapping
148
    /// @param hookData The data to pass through to the swap hooks
149
    /// @return swapDelta The balance delta of the address swapping
150
    /// @dev Swapping on low liquidity pools may cause unexpected swap amounts when liquidity available is less than amountSpecified.
151
    /// Additionally note that if interacting with hooks that have the BEFORE_SWAP_RETURNS_DELTA_FLAG or AFTER_SWAP_RETURNS_DELTA_FLAG
152
    /// the hook may alter the swap input/output. Integrators should perform checks on the returned swapDelta.
153
    function swap(PoolKey memory key, SwapParams memory params, bytes calldata hookData)
154
        external
155
        returns (BalanceDelta swapDelta);
156

                            
                        
157
    /// @notice Donate the given currency amounts to the pool with the given pool key
158
    /// @param key The key of the pool to donate to
159
    /// @param amount0 The amount of currency0 to donate
160
    /// @param amount1 The amount of currency1 to donate
161
    /// @param hookData The data to pass through to the donate hooks
162
    /// @return BalanceDelta The delta of the caller after the donate
163
    function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData)
164
        external
165
        returns (BalanceDelta);
166

                            
                        
167
    /// @notice Writes the current ERC20 balance of the specified currency to transient storage
168
    /// This is used to checkpoint balances for the manager and derive deltas for the caller.
169
    /// @dev This MUST be called before any ERC20 tokens are sent into the contract, but can be skipped
170
    /// for native tokens because the amount to settle is determined by the sent value.
171
    /// @param currency The currency whose balance to sync
172
    function sync(Currency currency) external;
173

                            
                        
174
    /// @notice Called by the user to net out some value owed to the user
175
    /// @dev Can also be used as a mechanism for _free_ flash loans
176
    /// @param currency The currency to withdraw from the pool manager
177
    /// @param to The address to withdraw to
178
    /// @param amount The amount of currency to withdraw
179
    function take(Currency currency, address to, uint256 amount) external;
180

                            
                        
181
    /// @notice Called by the user to pay what is owed
182
    /// @return paid The amount of currency settled
183
    function settle() external payable returns (uint256 paid);
184

                            
                        
185
    /// @notice Called by the user to pay on behalf of another address
186
    /// @param recipient The address to credit for the payment
187
    /// @return paid The amount of currency settled
188
    function settleFor(address recipient) external payable returns (uint256 paid);
189

                            
                        
190
    /// @notice WARNING - Any currency that is cleared, will be non-retreivable, and locked in the contract permanently.
191
    /// A call to clear will zero out a positive balance WITHOUT a corresponding transfer.
192
    /// @dev This could be used to clear a balance that is considered dust.
193
    /// Additionally, the amount must be the exact positive balance. This is to enforce that the caller is aware of the amount being cleared.
194
    function clear(Currency currency, uint256 amount) external;
195

                            
                        
196
    /// @notice Called by the user to move value into ERC6909 balance
197
    /// @param to The address to mint the tokens to
198
    /// @param id The currency address to mint to ERC6909s, as a uint256
199
    /// @param amount The amount of currency to mint
200
    /// @dev The id is converted to a uint160 to correspond to a currency address
201
    /// If the upper 12 bytes are not 0, they will be 0-ed out
202
    function mint(address to, uint256 id, uint256 amount) external;
203

                            
                        
204
    /// @notice Called by the user to move value from ERC6909 balance
205
    /// @param from The address to burn the tokens from
206
    /// @param id The currency address to burn from ERC6909s, as a uint256
207
    /// @param amount The amount of currency to burn
208
    /// @dev The id is converted to a uint160 to correspond to a currency address
209
    /// If the upper 12 bytes are not 0, they will be 0-ed out
210
    function burn(address from, uint256 id, uint256 amount) external;
211

                            
                        
212
    /// @notice Updates the pools lp fees for the a pool that has enabled dynamic lp fees.
213
    /// @param key The key of the pool to update dynamic LP fees for
214
    /// @param newDynamicLPFee The new dynamic pool LP fee
215
    function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external;
216
}
217

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {PoolKey} from "../types/PoolKey.sol";
5

                            
                        
6
/// @notice Interface to fetch the protocol fees for a pool from the protocol fee controller
7
interface IProtocolFeeController {
8
    /// @notice Returns the protocol fees for a pool given the conditions of this contract
9
    /// @param poolKey The pool key to identify the pool. The controller may want to use attributes on the pool
10
    ///   to determine the protocol fee, hence the entire key is needed.
11
    /// @return protocolFee The pool's protocol fee, expressed in hundredths of a bip. The upper 12 bits are for 1->0
12
    /// and the lower 12 are for 0->1. The maximum is 1000 - meaning the maximum protocol fee is 0.1%.
13
    /// the protocolFee is taken from the input first, then the lpFee is taken from the remaining input
14
    function protocolFeeForPool(PoolKey memory poolKey) external view returns (uint24 protocolFee);
15
}
16

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.19;
3

                            
                        
4
import {Currency} from "../types/Currency.sol";
5
import {IProtocolFeeController} from "../interfaces/IProtocolFeeController.sol";
6
import {PoolId} from "../types/PoolId.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8

                            
                        
9
/// @notice Interface for all protocol-fee related functions in the pool manager
10
interface IProtocolFees {
11
    /// @notice Thrown when not enough gas is provided to look up the protocol fee
12
    error ProtocolFeeCannotBeFetched();
13
    /// @notice Thrown when protocol fee is set too high
14
    error ProtocolFeeTooLarge(uint24 fee);
15

                            
                        
16
    /// @notice Thrown when collectProtocolFees or setProtocolFee is not called by the controller.
17
    error InvalidCaller();
18

                            
                        
19
    /// @notice Emitted when the protocol fee controller address is updated in setProtocolFeeController.
20
    event ProtocolFeeControllerUpdated(address indexed protocolFeeController);
21

                            
                        
22
    /// @notice Emitted when the protocol fee is updated for a pool.
23
    event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee);
24

                            
                        
25
    /// @notice Given a currency address, returns the protocol fees accrued in that currency
26
    /// @param currency The currency to check
27
    /// @return amount The amount of protocol fees accrued in the currency
28
    function protocolFeesAccrued(Currency currency) external view returns (uint256 amount);
29

                            
                        
30
    /// @notice Sets the protocol fee for the given pool
31
    /// @param key The key of the pool to set a protocol fee for
32
    /// @param newProtocolFee The fee to set
33
    function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external;
34

                            
                        
35
    /// @notice Sets the protocol fee controller
36
    /// @param controller The new protocol fee controller
37
    function setProtocolFeeController(IProtocolFeeController controller) external;
38

                            
                        
39
    /// @notice Collects the protocol fees for a given recipient and currency, returning the amount collected
40
    /// @param recipient The address to receive the protocol fees
41
    /// @param currency The currency to withdraw
42
    /// @param amount The amount of currency to withdraw
43
    /// @return amountCollected The amount of currency successfully withdrawn
44
    function collectProtocolFees(address recipient, Currency currency, uint256 amount)
45
        external
46
        returns (uint256 amountCollected);
47

                            
                        
48
    /// @notice Returns the current protocol fee controller address
49
    /// @return IProtocolFeeController The currency protocol fee controller
50
    function protocolFeeController() external view returns (IProtocolFeeController);
51
}
52

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @notice Interface for the callback executed when an address unlocks the pool manager
5
interface IUnlockCallback {
6
    /// @notice Called by the pool manager on `msg.sender` when the manager is unlocked
7
    /// @param data The data that was passed to the call to unlock
8
    /// @return Any data that you want to be returned from the unlock call
9
    function unlockCallback(bytes calldata data) external returns (bytes memory);
10
}
11

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @title Minimal ERC20 interface for Uniswap
5
/// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3
6
interface IERC20Minimal {
7
    /// @notice Returns an account's balance in the token
8
    /// @param account The account for which to look up the number of tokens it has, i.e. its balance
9
    /// @return The number of tokens held by the account
10
    function balanceOf(address account) external view returns (uint256);
11

                            
                        
12
    /// @notice Transfers the amount of token from the `msg.sender` to the recipient
13
    /// @param recipient The account that will receive the amount transferred
14
    /// @param amount The number of tokens to send from the sender to the recipient
15
    /// @return Returns true for a successful transfer, false for an unsuccessful transfer
16
    function transfer(address recipient, uint256 amount) external returns (bool);
17

                            
                        
18
    /// @notice Returns the current allowance given to a spender by an owner
19
    /// @param owner The account of the token owner
20
    /// @param spender The account of the token spender
21
    /// @return The current allowance granted by `owner` to `spender`
22
    function allowance(address owner, address spender) external view returns (uint256);
23

                            
                        
24
    /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount`
25
    /// @param spender The account which will be allowed to spend a given amount of the owners tokens
26
    /// @param amount The amount of tokens allowed to be used by `spender`
27
    /// @return Returns true for a successful approval, false for unsuccessful
28
    function approve(address spender, uint256 amount) external returns (bool);
29

                            
                        
30
    /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender`
31
    /// @param sender The account from which the transfer will be initiated
32
    /// @param recipient The recipient of the transfer
33
    /// @param amount The amount of the transfer
34
    /// @return Returns true for a successful transfer, false for unsuccessful
35
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
36

                            
                        
37
    /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`.
38
    /// @param from The account from which the tokens were sent, i.e. the balance decreased
39
    /// @param to The account to which the tokens were sent, i.e. the balance increased
40
    /// @param value The amount of tokens that were transferred
41
    event Transfer(address indexed from, address indexed to, uint256 value);
42

                            
                        
43
    /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes.
44
    /// @param owner The account that approved spending of its tokens
45
    /// @param spender The account for which the spending allowance was modified
46
    /// @param value The new allowance from the owner to the spender
47
    event Approval(address indexed owner, address indexed spender, uint256 value);
48
}
49

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @notice Interface for claims over a contract balance, wrapped as a ERC6909
5
interface IERC6909Claims {
6
    /*//////////////////////////////////////////////////////////////
7
                                 EVENTS
8
    //////////////////////////////////////////////////////////////*/
9

                            
                        
10
    event OperatorSet(address indexed owner, address indexed operator, bool approved);
11

                            
                        
12
    event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);
13

                            
                        
14
    event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount);
15

                            
                        
16
    /*//////////////////////////////////////////////////////////////
17
                                 FUNCTIONS
18
    //////////////////////////////////////////////////////////////*/
19

                            
                        
20
    /// @notice Owner balance of an id.
21
    /// @param owner The address of the owner.
22
    /// @param id The id of the token.
23
    /// @return amount The balance of the token.
24
    function balanceOf(address owner, uint256 id) external view returns (uint256 amount);
25

                            
                        
26
    /// @notice Spender allowance of an id.
27
    /// @param owner The address of the owner.
28
    /// @param spender The address of the spender.
29
    /// @param id The id of the token.
30
    /// @return amount The allowance of the token.
31
    function allowance(address owner, address spender, uint256 id) external view returns (uint256 amount);
32

                            
                        
33
    /// @notice Checks if a spender is approved by an owner as an operator
34
    /// @param owner The address of the owner.
35
    /// @param spender The address of the spender.
36
    /// @return approved The approval status.
37
    function isOperator(address owner, address spender) external view returns (bool approved);
38

                            
                        
39
    /// @notice Transfers an amount of an id from the caller to a receiver.
40
    /// @param receiver The address of the receiver.
41
    /// @param id The id of the token.
42
    /// @param amount The amount of the token.
43
    /// @return bool True, always, unless the function reverts
44
    function transfer(address receiver, uint256 id, uint256 amount) external returns (bool);
45

                            
                        
46
    /// @notice Transfers an amount of an id from a sender to a receiver.
47
    /// @param sender The address of the sender.
48
    /// @param receiver The address of the receiver.
49
    /// @param id The id of the token.
50
    /// @param amount The amount of the token.
51
    /// @return bool True, always, unless the function reverts
52
    function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool);
53

                            
                        
54
    /// @notice Approves an amount of an id to a spender.
55
    /// @param spender The address of the spender.
56
    /// @param id The id of the token.
57
    /// @param amount The amount of the token.
58
    /// @return bool True, always
59
    function approve(address spender, uint256 id, uint256 amount) external returns (bool);
60

                            
                        
61
    /// @notice Sets or removes an operator for the caller.
62
    /// @param operator The address of the operator.
63
    /// @param approved The approval status.
64
    /// @return bool True, always
65
    function setOperator(address operator, bool approved) external returns (bool);
66
}
67

                            
                        

Lines covered: 16 / 17 (94.1%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @title BitMath
5
/// @dev This library provides functionality for computing bit properties of an unsigned integer
6
/// @author Solady (https://github.com/Vectorized/solady/blob/8200a70e8dc2a77ecb074fc2e99a2a0d36547522/src/utils/LibBit.sol)
7
library BitMath {
8
    /// @notice Returns the index of the most significant bit of the number,
9
    ///     where the least significant bit is at index 0 and the most significant bit is at index 255
10
    /// @param x the value for which to compute the most significant bit, must be greater than 0
11
    /// @return r the index of the most significant bit
12
√ 1
⟳ 2
    function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {
13
√ 2
⟳ 4
        require(x > 0);
14

                            
                        
15
        assembly ("memory-safe") {
16
√ 5
⟳ 10
            r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x)))
17
√ 5
⟳ 10
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
18
√ 5
⟳ 10
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
19
√ 5
⟳ 10
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
20
√ 5
⟳ 10
            r := or(r, shl(3, lt(0xff, shr(r, x))))
21
            // forgefmt: disable-next-item
22
√ 5
⟳ 10
            r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
23
√ 1
⟳ 2
                0x0706060506020504060203020504030106050205030304010505030400000000))
24
        }
25
    }
26

                            
                        
27
    /// @notice Returns the index of the least significant bit of the number,
28
    ///     where the least significant bit is at index 0 and the most significant bit is at index 255
29
    /// @param x the value for which to compute the least significant bit, must be greater than 0
30
    /// @return r the index of the least significant bit
31
√ 1
⟳ 2
    function leastSignificantBit(uint256 x) internal pure returns (uint8 r) {
32
√ 2
⟳ 4
        require(x > 0);
33

                            
                        
34
        assembly ("memory-safe") {
35
            // Isolate the least significant bit.
36
√ 3
⟳ 6
            x := and(x, add(not(x), 1))
37
            // For the upper 3 bits of the result, use a De Bruijn-like lookup.
38
            // Credit to adhusson: https://blog.adhusson.com/cheap-find-first-set-evm/
39
            // forgefmt: disable-next-item
40
            r := shl(5, shr(252, shl(shl(2, shr(250, mul(x,
41
√ 1
⟳ 2
                0xb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff))),
42
√ 1
⟳ 2
                0x8040405543005266443200005020610674053026020000107506200176117077)))
43
            // For the lower 5 bits of the result, use a De Bruijn lookup.
44
            // forgefmt: disable-next-item
45
√ 5
⟳ 10
            r := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),
46
√ 1
⟳ 2
                0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
47
        }
48
    }
49
}
50

                            
                        

Lines covered: 8 / 9 (88.9%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Currency} from "../types/Currency.sol";
5

                            
                        
6
/// @title a library to store callers' currency deltas in transient storage
7
/// @dev this library implements the equivalent of a mapping, as transient storage can only be accessed in assembly
8
library CurrencyDelta {
9
    /// @notice calculates which storage slot a delta should be stored in for a given account and currency
10
    function _computeSlot(address target, Currency currency) internal pure returns (bytes32 hashSlot) {
11
        assembly ("memory-safe") {
12
√ 1
⟳ 1
            mstore(0, and(target, 0xffffffffffffffffffffffffffffffffffffffff))
13
√ 5
⟳ 5
            mstore(32, and(currency, 0xffffffffffffffffffffffffffffffffffffffff))
14
√ 2
⟳ 2
            hashSlot := keccak256(0, 64)
15
        }
16
    }
17

                            
                        
18
    function getDelta(Currency currency, address target) internal view returns (int256 delta) {
19
        bytes32 hashSlot = _computeSlot(target, currency);
20
        assembly {
21
√ 2
⟳ 2
            delta := tload(hashSlot)
22
        }
23
    }
24

                            
                        
25
    /// @notice applies a new currency delta for a given account and currency
26
    /// @return previous The prior value
27
    /// @return next The modified result
28
    function applyDelta(Currency currency, address target, int128 delta)
29
        internal
30
√ 2
⟳ 2
        returns (int256 previous, int256 next)
31
    {
32
        bytes32 hashSlot = _computeSlot(target, currency);
33

                            
                        
34
        assembly ("memory-safe") {
35
√ 4
⟳ 4
            previous := tload(hashSlot)
36
        }
37
√ 8
⟳ 8
        next = previous + delta;
38
        assembly ("memory-safe") {
39
√ 2
⟳ 2
            tstore(hashSlot, next)
40
        }
41
    }
42
}
43

                            
                        

Lines covered: 7 / 10 (70.0%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Currency} from "../types/Currency.sol";
5
import {CustomRevert} from "./CustomRevert.sol";
6

                            
                        
7
library CurrencyReserves {
8
    using CustomRevert for bytes4;
9

                            
                        
10
    /// @notice Thrown when a user has already synced a currency, but not yet settled
11
    error AlreadySynced();
12

                            
                        
13
    /// bytes32(uint256(keccak256("ReservesOf")) - 1)
14
    bytes32 constant RESERVES_OF_SLOT = 0x1e0745a7db1623981f0b2a5d4232364c00787266eb75ad546f190e6cebe9bd95;
15
    /// bytes32(uint256(keccak256("Currency")) - 1)
16
    bytes32 constant CURRENCY_SLOT = 0x27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b9;
17

                            
                        
18
    function requireNotSynced() internal view {
19
√ 3
⟳ 3
        if (!getSyncedCurrency().isZero()) {
20
⟳ 1
            AlreadySynced.selector.revertWith();
21
        }
22
    }
23

                            
                        
24
    function getSyncedCurrency() internal view returns (Currency currency) {
25
        assembly {
26
√ 2
⟳ 2
            currency := tload(CURRENCY_SLOT)
27
        }
28
    }
29

                            
                        
30
    function resetCurrency() internal {
31
        assembly {
32
√ 2
⟳ 2
            tstore(CURRENCY_SLOT, 0)
33
        }
34
    }
35

                            
                        
36
    function syncCurrencyAndReserves(Currency currency, uint256 value) internal {
37
        assembly {
38
√ 3
⟳ 3
            tstore(CURRENCY_SLOT, and(currency, 0xffffffffffffffffffffffffffffffffffffffff))
39
√ 2
⟳ 2
            tstore(RESERVES_OF_SLOT, value)
40
        }
41
    }
42

                            
                        
43
    function getSyncedReserves() internal view returns (uint256 value) {
44
        assembly {
45
√ 1
⟳ 1
            value := tload(RESERVES_OF_SLOT)
46
        }
47
    }
48
}
49

                            
                        

Lines covered: 26 / 34 (76.5%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @title Library for reverting with custom errors efficiently
5
/// @notice Contains functions for reverting with custom errors with different argument types efficiently
6
/// @dev To use this library, declare `using CustomRevert for bytes4;` and replace `revert CustomError()` with
7
/// `CustomError.selector.revertWith()`
8
/// @dev The functions may tamper with the free memory pointer but it is fine since the call context is exited immediately
9
library CustomRevert {
10
    /// @dev Reverts with the selector of a custom error in the scratch space
11
    function revertWith(bytes4 selector) internal pure {
12
        assembly ("memory-safe") {
13
⟳ 2
            mstore(0, selector)
14
⟳ 2
            revert(0, 0x04)
15
        }
16
    }
17

                            
                        
18
    /// @dev Reverts with a custom error with an address argument in the scratch space
19
    function revertWith(bytes4 selector, address addr) internal pure {
20
        assembly ("memory-safe") {
21
⟳ 2
            mstore(0, selector)
22
⟳ 3
            mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff))
23
⟳ 2
            revert(0, 0x24)
24
        }
25
    }
26

                            
                        
27
    /// @dev Reverts with a custom error with an int24 argument in the scratch space
28
    function revertWith(bytes4 selector, int24 value) internal pure {
29
        assembly ("memory-safe") {
30
⟳ 2
            mstore(0, selector)
31
⟳ 3
            mstore(0x04, signextend(2, value))
32
⟳ 2
            revert(0, 0x24)
33
        }
34
    }
35

                            
                        
36
    /// @dev Reverts with a custom error with a uint160 argument in the scratch space
37
    function revertWith(bytes4 selector, uint160 value) internal pure {
38
        assembly ("memory-safe") {
39
            mstore(0, selector)
40
            mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff))
41
            revert(0, 0x24)
42
        }
43
    }
44

                            
                        
45
    /// @dev Reverts with a custom error with two int24 arguments
46
    function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure {
47
        assembly ("memory-safe") {
48
⟳ 1
            let fmp := mload(0x40)
49
⟳ 2
            mstore(fmp, selector)
50
⟳ 4
            mstore(add(fmp, 0x04), signextend(2, value1))
51
⟳ 4
            mstore(add(fmp, 0x24), signextend(2, value2))
52
⟳ 2
            revert(fmp, 0x44)
53
        }
54
    }
55

                            
                        
56
    /// @dev Reverts with a custom error with two uint160 arguments
57
    function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure {
58
        assembly ("memory-safe") {
59
⟳ 1
            let fmp := mload(0x40)
60
⟳ 2
            mstore(fmp, selector)
61
⟳ 4
            mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff))
62
⟳ 4
            mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff))
63
⟳ 2
            revert(fmp, 0x44)
64
        }
65
    }
66

                            
                        
67
    /// @dev Reverts with a custom error with two address arguments
68
    function revertWith(bytes4 selector, address value1, address value2) internal pure {
69
        assembly ("memory-safe") {
70
            mstore(0, selector)
71
            mstore(0x04, and(value1, 0xffffffffffffffffffffffffffffffffffffffff))
72
            mstore(0x24, and(value2, 0xffffffffffffffffffffffffffffffffffffffff))
73
            revert(0, 0x44)
74
        }
75
    }
76

                            
                        
77
    /// @notice bubble up the revert message returned by a call and revert with the selector provided
78
    /// @dev this function should only be used with custom errors of the type `CustomError(bytes revertReason)`
79
    function bubbleUpAndRevertWith(bytes4 selector) internal pure {
80
        assembly ("memory-safe") {
81
⟳ 1
            let size := returndatasize()
82
⟳ 1
            let fmp := mload(0x40)
83

                            
                        
84
            // Encode selector, offset, size, data
85
⟳ 2
            mstore(fmp, selector)
86
⟳ 3
            mstore(add(fmp, 0x04), 0x20)
87
⟳ 3
            mstore(add(fmp, 0x24), size)
88
⟳ 4
            returndatacopy(add(fmp, 0x44), 0, size)
89

                            
                        
90
            // Ensure the size is a multiple of 32 bytes
91
⟳ 5
            let encodedSize := add(0x44, mul(div(add(size, 31), 32), 32))
92
⟳ 2
            revert(fmp, encodedSize)
93
        }
94
    }
95
}
96

                            
                        

Lines covered: 1 / 2 (50.0%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @title FixedPoint128
5
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
6
library FixedPoint128 {
7
√ 399
⟳ 6
    uint256 internal constant Q128 = 0x100000000000000000000000000000000;
8
}
9

                            
                        

Lines covered: 2 / 3 (66.7%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @title FixedPoint96
5
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
6
/// @dev Used in SqrtPriceMath.sol
7
library FixedPoint96 {
8
√ 4
⟳ 4
    uint8 internal constant RESOLUTION = 96;
9
√ 2
⟳ 2
    uint256 internal constant Q96 = 0x1000000000000000000000000;
10
}
11

                            
                        

Lines covered: 29 / 30 (96.7%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @title Contains 512-bit math functions
5
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
6
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
7
library FullMath {
8
    /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
9
    /// @param a The multiplicand
10
    /// @param b The multiplier
11
    /// @param denominator The divisor
12
    /// @return result The 256-bit result
13
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
14
√ 8
⟳ 4
    function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
15
        unchecked {
16
            // 512-bit multiply [prod1 prod0] = a * b
17
            // Compute the product mod 2**256 and mod 2**256 - 1
18
            // then use the Chinese Remainder Theorem to reconstruct
19
            // the 512 bit result. The result is stored in two 256
20
            // variables such that product = prod1 * 2**256 + prod0
21
√ 8
⟳ 4
            uint256 prod0 = a * b; // Least significant 256 bits of the product
22
            uint256 prod1; // Most significant 256 bits of the product
23
            assembly ("memory-safe") {
24
√ 4
⟳ 2
                let mm := mulmod(a, b, not(0))
25
√ 16
⟳ 8
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
26
            }
27

                            
                        
28
            // Make sure the result is less than 2**256.
29
            // Also prevents denominator == 0
30
√ 8
⟳ 4
            require(denominator > prod1);
31

                            
                        
32
            // Handle non-overflow cases, 256 by 256 division
33
√ 8
⟳ 4
            if (prod1 == 0) {
34
                assembly ("memory-safe") {
35
√ 16
⟳ 8
                    result := div(prod0, denominator)
36
                }
37
√ 8
⟳ 4
                return result;
38
            }
39

                            
                        
40
            ///////////////////////////////////////////////
41
            // 512 by 256 division.
42
            ///////////////////////////////////////////////
43

                            
                        
44
            // Make division exact by subtracting the remainder from [prod1 prod0]
45
            // Compute remainder using mulmod
46
√ 1
⟳ 3467
            uint256 remainder;
47
            assembly ("memory-safe") {
48
√ 3
⟳ 10401
                remainder := mulmod(a, b, denominator)
49
            }
50
            // Subtract 256 bit number from 512 bit number
51
            assembly ("memory-safe") {
52
√ 3
⟳ 10401
                prod1 := sub(prod1, gt(remainder, prod0))
53
√ 4
⟳ 13868
                prod0 := sub(prod0, remainder)
54
            }
55

                            
                        
56
            // Factor powers of two out of denominator
57
            // Compute largest power of two divisor of denominator.
58
            // Always >= 1.
59
√ 4
⟳ 13868
            uint256 twos = (0 - denominator) & denominator;
60
            // Divide denominator by power of two
61
            assembly ("memory-safe") {
62
√ 5
⟳ 17335
                denominator := div(denominator, twos)
63
            }
64

                            
                        
65
            // Divide [prod1 prod0] by the factors of two
66
            assembly ("memory-safe") {
67
√ 4
⟳ 13868
                prod0 := div(prod0, twos)
68
            }
69
            // Shift in bits from prod1 into prod0. For this we need
70
            // to flip `twos` such that it is 2**256 / twos.
71
            // If twos is zero, then it becomes one
72
            assembly ("memory-safe") {
73
√ 5
⟳ 17335
                twos := add(div(sub(0, twos), twos), 1)
74
            }
75
√ 4
⟳ 13868
            prod0 |= prod1 * twos;
76

                            
                        
77
            // Invert denominator mod 2**256
78
            // Now that denominator is an odd number, it has an inverse
79
            // modulo 2**256 such that denominator * inv = 1 mod 2**256.
80
            // Compute the inverse by starting with a seed that is correct
81
            // correct for four bits. That is, denominator * inv = 1 mod 2**4
82
√ 2
⟳ 6934
            uint256 inv = (3 * denominator) ^ 2;
83
            // Now use Newton-Raphson iteration to improve the precision.
84
            // Thanks to Hensel's lifting lemma, this also works in modular
85
            // arithmetic, doubling the correct bits in each step.
86
√ 3
⟳ 10401
            inv *= 2 - denominator * inv; // inverse mod 2**8
87
√ 3
⟳ 10401
            inv *= 2 - denominator * inv; // inverse mod 2**16
88
√ 3
⟳ 10401
            inv *= 2 - denominator * inv; // inverse mod 2**32
89
√ 3
⟳ 10401
            inv *= 2 - denominator * inv; // inverse mod 2**64
90
√ 3
⟳ 10401
            inv *= 2 - denominator * inv; // inverse mod 2**128
91
√ 3
⟳ 10401
            inv *= 2 - denominator * inv; // inverse mod 2**256
92

                            
                        
93
            // Because the division is now exact we can divide by multiplying
94
            // with the modular inverse of denominator. This will give us the
95
            // correct result modulo 2**256. Since the preconditions guarantee
96
            // that the outcome is less than 2**256, this is the final result.
97
            // We don't need to compute the high bits of the result and prod1
98
            // is no longer required.
99
√ 5
⟳ 17335
            result = prod0 * inv;
100
            return result;
101
        }
102
    }
103

                            
                        
104
    /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
105
    /// @param a The multiplicand
106
    /// @param b The multiplier
107
    /// @param denominator The divisor
108
    /// @return result The 256-bit result
109
√ 1
⟳ 1
    function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
110
        unchecked {
111
√ 4
⟳ 4
            result = mulDiv(a, b, denominator);
112
√ 3
⟳ 3
            if (mulmod(a, b, denominator) != 0) {
113
√ 2
⟳ 2
                require(++result > 0);
114
            }
115
        }
116
    }
117
}
118

                            
                        

Lines covered: 44 / 109 (40.4%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {PoolKey} from "../types/PoolKey.sol";
5
import {IHooks} from "../interfaces/IHooks.sol";
6
import {SafeCast} from "./SafeCast.sol";
7
import {LPFeeLibrary} from "./LPFeeLibrary.sol";
8
import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
9
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
10
import {IPoolManager} from "../interfaces/IPoolManager.sol";
11
import {ParseBytes} from "./ParseBytes.sol";
12
import {CustomRevert} from "./CustomRevert.sol";
13

                            
                        
14
/// @notice V4 decides whether to invoke specific hooks by inspecting the lowest significant bits of the address that
15
/// the hooks contract is deployed to.
16
/// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400
17
/// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used.
18
library Hooks {
19
    using LPFeeLibrary for uint24;
20
    using Hooks for IHooks;
21
    using SafeCast for int256;
22
    using BeforeSwapDeltaLibrary for BeforeSwapDelta;
23
    using ParseBytes for bytes;
24
    using CustomRevert for bytes4;
25

                            
                        
26
    uint160 internal constant ALL_HOOK_MASK = uint160((1 << 14) - 1);
27

                            
                        
28
√ 1
⟳ 1
    uint160 internal constant BEFORE_INITIALIZE_FLAG = 1 << 13;
29
√ 1
⟳ 1
    uint160 internal constant AFTER_INITIALIZE_FLAG = 1 << 12;
30

                            
                        
31
√ 1
⟳ 1
    uint160 internal constant BEFORE_ADD_LIQUIDITY_FLAG = 1 << 11;
32
√ 2
⟳ 2
    uint160 internal constant AFTER_ADD_LIQUIDITY_FLAG = 1 << 10;
33

                            
                        
34
√ 1
⟳ 1
    uint160 internal constant BEFORE_REMOVE_LIQUIDITY_FLAG = 1 << 9;
35
√ 2
⟳ 1
    uint160 internal constant AFTER_REMOVE_LIQUIDITY_FLAG = 1 << 8;
36

                            
                        
37
√ 2
⟳ 2
    uint160 internal constant BEFORE_SWAP_FLAG = 1 << 7;
38
√ 2
⟳ 2
    uint160 internal constant AFTER_SWAP_FLAG = 1 << 6;
39

                            
                        
40
√ 1
⟳ 1
    uint160 internal constant BEFORE_DONATE_FLAG = 1 << 5;
41
√ 1
⟳ 1
    uint160 internal constant AFTER_DONATE_FLAG = 1 << 4;
42

                            
                        
43
√ 1
⟳ 1
    uint160 internal constant BEFORE_SWAP_RETURNS_DELTA_FLAG = 1 << 3;
44
√ 1
⟳ 1
    uint160 internal constant AFTER_SWAP_RETURNS_DELTA_FLAG = 1 << 2;
45
√ 1
⟳ 1
    uint160 internal constant AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 1;
46
√ 1
⟳ 1
    uint160 internal constant AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 0;
47

                            
                        
48
    struct Permissions {
49
        bool beforeInitialize;
50
        bool afterInitialize;
51
        bool beforeAddLiquidity;
52
        bool afterAddLiquidity;
53
        bool beforeRemoveLiquidity;
54
        bool afterRemoveLiquidity;
55
        bool beforeSwap;
56
        bool afterSwap;
57
        bool beforeDonate;
58
        bool afterDonate;
59
        bool beforeSwapReturnDelta;
60
        bool afterSwapReturnDelta;
61
        bool afterAddLiquidityReturnDelta;
62
        bool afterRemoveLiquidityReturnDelta;
63
    }
64

                            
                        
65
    /// @notice Thrown if the address will not lead to the specified hook calls being called
66
    /// @param hooks The address of the hooks contract
67
    error HookAddressNotValid(address hooks);
68

                            
                        
69
    /// @notice Hook did not return its selector
70
    error InvalidHookResponse();
71

                            
                        
72
    /// @notice thrown when a hook call fails
73
    /// @param revertReason bubbled up revert reason
74
    error FailedHookCall(bytes revertReason);
75

                            
                        
76
    /// @notice The hook's delta changed the swap from exactIn to exactOut or vice versa
77
    error HookDeltaExceedsSwapAmount();
78

                            
                        
79
    /// @notice Utility function intended to be used in hook constructors to ensure
80
    /// the deployed hooks address causes the intended hooks to be called
81
    /// @param permissions The hooks that are intended to be called
82
    /// @dev permissions param is memory as the function will be called from constructors
83
    function validateHookPermissions(IHooks self, Permissions memory permissions) internal pure {
84
        if (
85
            permissions.beforeInitialize != self.hasPermission(BEFORE_INITIALIZE_FLAG)
86
                || permissions.afterInitialize != self.hasPermission(AFTER_INITIALIZE_FLAG)
87
                || permissions.beforeAddLiquidity != self.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG)
88
                || permissions.afterAddLiquidity != self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG)
89
                || permissions.beforeRemoveLiquidity != self.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG)
90
                || permissions.afterRemoveLiquidity != self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG)
91
                || permissions.beforeSwap != self.hasPermission(BEFORE_SWAP_FLAG)
92
                || permissions.afterSwap != self.hasPermission(AFTER_SWAP_FLAG)
93
                || permissions.beforeDonate != self.hasPermission(BEFORE_DONATE_FLAG)
94
                || permissions.afterDonate != self.hasPermission(AFTER_DONATE_FLAG)
95
                || permissions.beforeSwapReturnDelta != self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)
96
                || permissions.afterSwapReturnDelta != self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG)
97
                || permissions.afterAddLiquidityReturnDelta != self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)
98
                || permissions.afterRemoveLiquidityReturnDelta
99
                    != self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)
100
        ) {
101
            HookAddressNotValid.selector.revertWith(address(self));
102
        }
103
    }
104

                            
                        
105
    /// @notice Ensures that the hook address includes at least one hook flag or dynamic fees, or is the 0 address
106
    /// @param self The hook to verify
107
    /// @param fee The fee of the pool the hook is used with
108
    /// @return bool True if the hook address is valid
109
√ 1
⟳ 1
    function isValidHookAddress(IHooks self, uint24 fee) internal pure returns (bool) {
110
        // The hook can only have a flag to return a hook delta on an action if it also has the corresponding action flag
111
√ 1
⟳ 1
        if (!self.hasPermission(BEFORE_SWAP_FLAG) && self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) return false;
112
√ 1
⟳ 1
        if (!self.hasPermission(AFTER_SWAP_FLAG) && self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG)) return false;
113
√ 1
⟳ 1
        if (!self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG) && self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG))
114
        {
115
            return false;
116
        }
117
        if (
118
            !self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG)
119
√ 1
⟳ 1
                && self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)
120
        ) return false;
121

                            
                        
122
        // If there is no hook contract set, then fee cannot be dynamic
123
        // If a hook contract is set, it must have at least 1 flag set, or have a dynamic fee
124
√ 4
⟳ 4
        return address(self) == address(0)
125
√ 2
⟳ 2
            ? !fee.isDynamicFee()
126
            : (uint160(address(self)) & ALL_HOOK_MASK > 0 || fee.isDynamicFee());
127
    }
128

                            
                        
129
    /// @notice performs a hook call using the given calldata on the given hook that doesnt return a delta
130
    /// @return result The complete data returned by the hook
131
    function callHook(IHooks self, bytes memory data) internal returns (bytes memory result) {
132
        bool success;
133
        assembly ("memory-safe") {
134
            success := call(gas(), self, 0, add(data, 0x20), mload(data), 0, 0)
135
        }
136
        // Revert with FailedHookCall, containing any error message to bubble up
137
        if (!success) FailedHookCall.selector.bubbleUpAndRevertWith();
138

                            
                        
139
        // The call was successful, fetch the returned data
140
        assembly ("memory-safe") {
141
            // allocate result byte array from the free memory pointer
142
            result := mload(0x40)
143
            // store new free memory pointer at the end of the array padded to 32 bytes
144
            mstore(0x40, add(result, and(add(returndatasize(), 0x3f), not(0x1f))))
145
            // store length in memory
146
            mstore(result, returndatasize())
147
            // copy return data to result
148
            returndatacopy(add(result, 0x20), 0, returndatasize())
149
        }
150

                            
                        
151
        // Length must be at least 32 to contain the selector. Check expected selector and returned selector match.
152
        if (result.length < 32 || result.parseSelector() != data.parseSelector()) {
153
            InvalidHookResponse.selector.revertWith();
154
        }
155
    }
156

                            
                        
157
    /// @notice performs a hook call using the given calldata on the given hook
158
    /// @return int256 The delta returned by the hook
159
    function callHookWithReturnDelta(IHooks self, bytes memory data, bool parseReturn) internal returns (int256) {
160
        bytes memory result = callHook(self, data);
161

                            
                        
162
        // If this hook wasnt meant to return something, default to 0 delta
163
        if (!parseReturn) return 0;
164

                            
                        
165
        // A length of 64 bytes is required to return a bytes4, and a 32 byte delta
166
        if (result.length != 64) InvalidHookResponse.selector.revertWith();
167
        return result.parseReturnDelta();
168
    }
169

                            
                        
170
    /// @notice modifier to prevent calling a hook if they initiated the action
171
    modifier noSelfCall(IHooks self) {
172
√ 5
⟳ 5
        if (msg.sender != address(self)) {
173
            _;
174
        }
175
    }
176

                            
                        
177
    /// @notice calls beforeInitialize hook if permissioned and validates return value
178
    function beforeInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData)
179
        internal
180
√ 1
⟳ 1
        noSelfCall(self)
181
    {
182
        if (self.hasPermission(BEFORE_INITIALIZE_FLAG)) {
183
            self.callHook(abi.encodeCall(IHooks.beforeInitialize, (msg.sender, key, sqrtPriceX96, hookData)));
184
        }
185
    }
186

                            
                        
187
    /// @notice calls afterInitialize hook if permissioned and validates return value
188
    function afterInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, int24 tick, bytes calldata hookData)
189
        internal
190
√ 1
⟳ 1
        noSelfCall(self)
191
    {
192
        if (self.hasPermission(AFTER_INITIALIZE_FLAG)) {
193
            self.callHook(abi.encodeCall(IHooks.afterInitialize, (msg.sender, key, sqrtPriceX96, tick, hookData)));
194
        }
195
    }
196

                            
                        
197
    /// @notice calls beforeModifyLiquidity hook if permissioned and validates return value
198
    function beforeModifyLiquidity(
199
        IHooks self,
200
        PoolKey memory key,
201
        IPoolManager.ModifyLiquidityParams memory params,
202
        bytes calldata hookData
203
√ 1
⟳ 1
    ) internal noSelfCall(self) {
204
√ 3
⟳ 3
        if (params.liquidityDelta > 0 && self.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG)) {
205
            self.callHook(abi.encodeCall(IHooks.beforeAddLiquidity, (msg.sender, key, params, hookData)));
206
√ 3
⟳ 3
        } else if (params.liquidityDelta <= 0 && self.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG)) {
207
            self.callHook(abi.encodeCall(IHooks.beforeRemoveLiquidity, (msg.sender, key, params, hookData)));
208
        }
209
    }
210

                            
                        
211
    /// @notice calls afterModifyLiquidity hook if permissioned and validates return value
212
    function afterModifyLiquidity(
213
        IHooks self,
214
        PoolKey memory key,
215
        IPoolManager.ModifyLiquidityParams memory params,
216
        BalanceDelta delta,
217
        bytes calldata hookData
218
√ 2
⟳ 2
    ) internal returns (BalanceDelta callerDelta, BalanceDelta hookDelta) {
219
√ 1
⟳ 1
        if (msg.sender == address(self)) return (delta, BalanceDeltaLibrary.ZERO_DELTA);
220

                            
                        
221
√ 1
⟳ 1
        callerDelta = delta;
222
√ 2
⟳ 2
        if (params.liquidityDelta > 0) {
223
            if (self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG)) {
224
                hookDelta = BalanceDelta.wrap(
225
                    self.callHookWithReturnDelta(
226
                        abi.encodeCall(IHooks.afterAddLiquidity, (msg.sender, key, params, delta, hookData)),
227
                        self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)
228
                    )
229
                );
230
                callerDelta = callerDelta - hookDelta;
231
            }
232
        } else {
233
            if (self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG)) {
234
                hookDelta = BalanceDelta.wrap(
235
                    self.callHookWithReturnDelta(
236
                        abi.encodeCall(IHooks.afterRemoveLiquidity, (msg.sender, key, params, delta, hookData)),
237
                        self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)
238
                    )
239
                );
240
                callerDelta = callerDelta - hookDelta;
241
            }
242
        }
243
    }
244

                            
                        
245
    /// @notice calls beforeSwap hook if permissioned and validates return value
246
    function beforeSwap(IHooks self, PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData)
247
        internal
248
√ 2
⟳ 2
        returns (int256 amountToSwap, BeforeSwapDelta hookReturn, uint24 lpFeeOverride)
249
    {
250
√ 4
⟳ 4
        amountToSwap = params.amountSpecified;
251
√ 1
⟳ 1
        if (msg.sender == address(self)) return (amountToSwap, BeforeSwapDeltaLibrary.ZERO_DELTA, lpFeeOverride);
252

                            
                        
253
        if (self.hasPermission(BEFORE_SWAP_FLAG)) {
254
            bytes memory result = callHook(self, abi.encodeCall(IHooks.beforeSwap, (msg.sender, key, params, hookData)));
255

                            
                        
256
            // A length of 96 bytes is required to return a bytes4, a 32 byte delta, and an LP fee
257
            if (result.length != 96) InvalidHookResponse.selector.revertWith();
258

                            
                        
259
            // dynamic fee pools that do not want to override the cache fee, return 0 otherwise they return a valid fee with the override flag
260
            if (key.fee.isDynamicFee()) lpFeeOverride = result.parseFee();
261

                            
                        
262
            // skip this logic for the case where the hook return is 0
263
            if (self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) {
264
                hookReturn = BeforeSwapDelta.wrap(result.parseReturnDelta());
265

                            
                        
266
                // any return in unspecified is passed to the afterSwap hook for handling
267
                int128 hookDeltaSpecified = hookReturn.getSpecifiedDelta();
268

                            
                        
269
                // Update the swap amount according to the hook's return, and check that the swap type doesnt change (exact input/output)
270
                if (hookDeltaSpecified != 0) {
271
                    bool exactInput = amountToSwap < 0;
272
                    amountToSwap += hookDeltaSpecified;
273
                    if (exactInput ? amountToSwap > 0 : amountToSwap < 0) {
274
                        HookDeltaExceedsSwapAmount.selector.revertWith();
275
                    }
276
                }
277
            }
278
        }
279
    }
280

                            
                        
281
    /// @notice calls afterSwap hook if permissioned and validates return value
282
    function afterSwap(
283
        IHooks self,
284
        PoolKey memory key,
285
        IPoolManager.SwapParams memory params,
286
        BalanceDelta swapDelta,
287
        bytes calldata hookData,
288
        BeforeSwapDelta beforeSwapHookReturn
289
√ 2
⟳ 2
    ) internal returns (BalanceDelta, BalanceDelta) {
290
√ 1
⟳ 1
        if (msg.sender == address(self)) return (swapDelta, BalanceDeltaLibrary.ZERO_DELTA);
291

                            
                        
292
√ 2
⟳ 2
        int128 hookDeltaSpecified = beforeSwapHookReturn.getSpecifiedDelta();
293
√ 2
⟳ 2
        int128 hookDeltaUnspecified = beforeSwapHookReturn.getUnspecifiedDelta();
294

                            
                        
295
        if (self.hasPermission(AFTER_SWAP_FLAG)) {
296
            hookDeltaUnspecified += self.callHookWithReturnDelta(
297
                abi.encodeCall(IHooks.afterSwap, (msg.sender, key, params, swapDelta, hookData)),
298
                self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG)
299
            ).toInt128();
300
        }
301

                            
                        
302
√ 1
⟳ 1
        BalanceDelta hookDelta;
303
√ 4
⟳ 4
        if (hookDeltaUnspecified != 0 || hookDeltaSpecified != 0) {
304
            hookDelta = (params.amountSpecified < 0 == params.zeroForOne)
305
                ? toBalanceDelta(hookDeltaSpecified, hookDeltaUnspecified)
306
                : toBalanceDelta(hookDeltaUnspecified, hookDeltaSpecified);
307

                            
                        
308
            // the caller has to pay for (or receive) the hook's delta
309
            swapDelta = swapDelta - hookDelta;
310
        }
311
√ 3
⟳ 3
        return (swapDelta, hookDelta);
312
    }
313

                            
                        
314
    /// @notice calls beforeDonate hook if permissioned and validates return value
315
    function beforeDonate(IHooks self, PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData)
316
        internal
317
√ 1
⟳ 1
        noSelfCall(self)
318
    {
319
        if (self.hasPermission(BEFORE_DONATE_FLAG)) {
320
            self.callHook(abi.encodeCall(IHooks.beforeDonate, (msg.sender, key, amount0, amount1, hookData)));
321
        }
322
    }
323

                            
                        
324
    /// @notice calls afterDonate hook if permissioned and validates return value
325
    function afterDonate(IHooks self, PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData)
326
        internal
327
√ 1
⟳ 1
        noSelfCall(self)
328
    {
329
        if (self.hasPermission(AFTER_DONATE_FLAG)) {
330
            self.callHook(abi.encodeCall(IHooks.afterDonate, (msg.sender, key, amount0, amount1, hookData)));
331
        }
332
    }
333

                            
                        
334
    function hasPermission(IHooks self, uint160 flag) internal pure returns (bool) {
335
√ 36
⟳ 34
        return uint160(address(self)) & flag != 0;
336
    }
337
}
338

                            
                        

Lines covered: 10 / 15 (66.7%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {CustomRevert} from "./CustomRevert.sol";
5

                            
                        
6
/// @notice Library of helper functions for a pools LP fee
7
library LPFeeLibrary {
8
    using LPFeeLibrary for uint24;
9
    using CustomRevert for bytes4;
10

                            
                        
11
    /// @notice Thrown when the static or dynamic fee on a pool exceeds 100%.
12
    error LPFeeTooLarge(uint24 fee);
13

                            
                        
14
    /// @notice An lp fee of exactly 0b1000000... signals a dynamic fee pool. This isnt a valid static fee as it is > MAX_LP_FEE
15
√ 2
⟳ 3
    uint24 public constant DYNAMIC_FEE_FLAG = 0x800000;
16

                            
                        
17
    /// @notice the second bit of the fee returned by beforeSwap is used to signal if the stored LP fee should be overridden in this swap
18
    // only dynamic-fee pools can return a fee via the beforeSwap hook
19
√ 1
⟳ 1
    uint24 public constant OVERRIDE_FEE_FLAG = 0x400000;
20

                            
                        
21
    /// @notice mask to remove the override fee flag from a fee returned by the beforeSwaphook
22
    uint24 public constant REMOVE_OVERRIDE_MASK = 0xBFFFFF;
23

                            
                        
24
    /// @notice the lp fee is represented in hundredths of a bip, so the max is 100%
25
√ 2
⟳ 2
    uint24 public constant MAX_LP_FEE = 1000000;
26

                            
                        
27
    /// @notice returns true if a pool's LP fee signals that the pool has a dynamic fee
28
    /// @param self The fee to check
29
    /// @return bool True of the fee is dynamic
30
    function isDynamicFee(uint24 self) internal pure returns (bool) {
31
√ 2
⟳ 3
        return self == DYNAMIC_FEE_FLAG;
32
    }
33

                            
                        
34
    /// @notice returns true if an LP fee is valid, aka not above the maxmimum permitted fee
35
    /// @param self The fee to check
36
    /// @return bool True of the fee is valid
37
    function isValid(uint24 self) internal pure returns (bool) {
38
√ 2
⟳ 2
        return self <= MAX_LP_FEE;
39
    }
40

                            
                        
41
    /// @notice validates whether an LP fee is larger than the maximum, and reverts if invalid
42
    /// @param self The fee to validate
43
    function validate(uint24 self) internal pure {
44
√ 3
⟳ 4
        if (!self.isValid()) LPFeeTooLarge.selector.revertWith(self);
45
    }
46

                            
                        
47
    /// @notice gets and validates the initial LP fee for a pool. Dynamic fee pools have an initial fee of 0.
48
    /// @dev if a dynamic fee pool wants a non-0 initial fee, it should call `updateDynamicLPFee` in the afterInitialize hook
49
    /// @param self The fee to get the initial LP from
50
    /// @return initialFee 0 if the fee is dynamic, otherwise the fee (if valid)
51
√ 1
⟳ 1
    function getInitialLPFee(uint24 self) internal pure returns (uint24) {
52
        // the initial fee for a dynamic fee pool is 0
53
√ 3
⟳ 3
        if (self.isDynamicFee()) return 0;
54
√ 1
⟳ 1
        self.validate();
55
        return self;
56
    }
57

                            
                        
58
    /// @notice returns true if the fee has the override flag set (2nd highest bit of the uint24)
59
    /// @param self The fee to check
60
    /// @return bool True of the fee has the override flag set
61
    function isOverride(uint24 self) internal pure returns (bool) {
62
√ 1
⟳ 1
        return self & OVERRIDE_FEE_FLAG != 0;
63
    }
64

                            
                        
65
    /// @notice returns a fee with the override flag removed
66
    /// @param self The fee to remove the override flag from
67
    /// @return fee The fee without the override flag set
68
    function removeOverrideFlag(uint24 self) internal pure returns (uint24) {
69
        return self & REMOVE_OVERRIDE_MASK;
70
    }
71

                            
                        
72
    /// @notice Removes the override flag and validates the fee (reverts if the fee is too large)
73
    /// @param self The fee to remove the override flag from, and then validate
74
    /// @return fee The fee without the override flag set (if valid)
75
    function removeOverrideFlagAndValidate(uint24 self) internal pure returns (uint24 fee) {
76
        fee = self.removeOverrideFlag();
77
        fee.validate();
78
    }
79
}
80

                            
                        

Lines covered: 2 / 5 (40.0%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @title Math library for liquidity
5
library LiquidityMath {
6
    /// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows
7
    /// @param x The liquidity before change
8
    /// @param y The delta by which liquidity should be changed
9
    /// @return z The liquidity delta
10
    function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) {
11
        assembly ("memory-safe") {
12
√ 8
⟳ 8
            z := add(and(x, 0xffffffffffffffffffffffffffffffff), signextend(15, y))
13
√ 4
⟳ 4
            if shr(128, z) {
14
                // revert SafeCastOverflow()
15
                mstore(0, 0x93dafdf1)
16
                revert(0x1c, 0x04)
17
            }
18
        }
19
    }
20
}
21

                            
                        

Lines covered: 3 / 5 (60.0%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.24;
3

                            
                        
4
/// @notice This is a temporary library that allows us to use transient storage (tstore/tload)
5
/// TODO: This library can be deleted when we have the transient keyword support in solidity.
6
library Lock {
7
    // The slot holding the unlocked state, transiently. bytes32(uint256(keccak256("Unlocked")) - 1)
8
    bytes32 internal constant IS_UNLOCKED_SLOT = 0xc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab23;
9

                            
                        
10
    function unlock() internal {
11
        assembly ("memory-safe") {
12
            // unlock
13
√ 2
⟳ 2
            tstore(IS_UNLOCKED_SLOT, true)
14
        }
15
    }
16

                            
                        
17
    function lock() internal {
18
        assembly ("memory-safe") {
19
√ 2
⟳ 2
            tstore(IS_UNLOCKED_SLOT, false)
20
        }
21
    }
22

                            
                        
23
    function isUnlocked() internal view returns (bool unlocked) {
24
        assembly ("memory-safe") {
25
√ 10
⟳ 10
            unlocked := tload(IS_UNLOCKED_SLOT)
26
        }
27
    }
28
}
29

                            
                        

Lines covered: 7 / 9 (77.8%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.24;
3

                            
                        
4
/// @notice This is a temporary library that allows us to use transient storage (tstore/tload)
5
/// for the nonzero delta count.
6
/// TODO: This library can be deleted when we have the transient keyword support in solidity.
7
library NonZeroDeltaCount {
8
    // The slot holding the number of nonzero deltas. bytes32(uint256(keccak256("NonzeroDeltaCount")) - 1)
9
    bytes32 internal constant NONZERO_DELTA_COUNT_SLOT =
10
        0x7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b;
11

                            
                        
12
    function read() internal view returns (uint256 count) {
13
        assembly ("memory-safe") {
14
√ 1
⟳ 1
            count := tload(NONZERO_DELTA_COUNT_SLOT)
15
        }
16
    }
17

                            
                        
18
    function increment() internal {
19
        assembly ("memory-safe") {
20
√ 1
⟳ 2
            let count := tload(NONZERO_DELTA_COUNT_SLOT)
21
√ 2
⟳ 4
            count := add(count, 1)
22
√ 2
⟳ 4
            tstore(NONZERO_DELTA_COUNT_SLOT, count)
23
        }
24
    }
25

                            
                        
26
    /// @notice Potential to underflow. Ensure checks are performed by integrating contracts to ensure this does not happen.
27
    /// Current usage ensures this will not happen because we call decrement with known boundaries (only up to the number of times we call increment).
28
    function decrement() internal {
29
        assembly ("memory-safe") {
30
√ 1
⟳ 1
            let count := tload(NONZERO_DELTA_COUNT_SLOT)
31
√ 2
⟳ 2
            count := sub(count, 1)
32
√ 2
⟳ 2
            tstore(NONZERO_DELTA_COUNT_SLOT, count)
33
        }
34
    }
35
}
36

                            
                        

Lines covered: 0 / 4 (0.0%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2

                            
                        
3
pragma solidity ^0.8.0;
4

                            
                        
5
/// @notice Parses bytes returned from hooks and the byte selector used to check return selectors from hooks.
6
/// @dev parseSelector also is used to parse the expected selector
7
/// For parsing hook returns, note that all hooks return either bytes4 or (bytes4, 32-byte-delta) or (bytes4, 32-byte-delta, uint24).
8
library ParseBytes {
9
    function parseSelector(bytes memory result) internal pure returns (bytes4 selector) {
10
        // equivalent: (selector,) = abi.decode(result, (bytes4, int256));
11
        assembly ("memory-safe") {
12
            selector := mload(add(result, 0x20))
13
        }
14
    }
15

                            
                        
16
    function parseFee(bytes memory result) internal pure returns (uint24 lpFee) {
17
        // equivalent: (,, lpFee) = abi.decode(result, (bytes4, int256, uint24));
18
        assembly ("memory-safe") {
19
            lpFee := mload(add(result, 0x60))
20
        }
21
    }
22

                            
                        
23
    function parseReturnDelta(bytes memory result) internal pure returns (int256 hookReturn) {
24
        // equivalent: (, hookReturnDelta) = abi.decode(result, (bytes4, int256));
25
        assembly ("memory-safe") {
26
            hookReturn := mload(add(result, 0x40))
27
        }
28
    }
29
}
30

                            
                        

Lines covered: 171 / 177 (96.6%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {SafeCast} from "./SafeCast.sol";
5
import {TickBitmap} from "./TickBitmap.sol";
6
import {Position} from "./Position.sol";
7
import {FullMath} from "./FullMath.sol";
8
import {FixedPoint128} from "./FixedPoint128.sol";
9
import {TickMath} from "./TickMath.sol";
10
import {SqrtPriceMath} from "./SqrtPriceMath.sol";
11
import {SwapMath} from "./SwapMath.sol";
12
import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
13
import {Slot0} from "../types/Slot0.sol";
14
import {ProtocolFeeLibrary} from "./ProtocolFeeLibrary.sol";
15
import {LiquidityMath} from "./LiquidityMath.sol";
16
import {LPFeeLibrary} from "./LPFeeLibrary.sol";
17
import {CustomRevert} from "./CustomRevert.sol";
18

                            
                        
19
/// @notice a library with all actions that can be performed on a pool
20
library Pool {
21
    using SafeCast for *;
22
    using TickBitmap for mapping(int16 => uint256);
23
    using Position for mapping(bytes32 => Position.Info);
24
    using Position for Position.Info;
25
    using Pool for State;
26
    using ProtocolFeeLibrary for *;
27
    using LPFeeLibrary for uint24;
28
    using CustomRevert for bytes4;
29

                            
                        
30
    /// @notice Thrown when tickLower is not below tickUpper
31
    /// @param tickLower The invalid tickLower
32
    /// @param tickUpper The invalid tickUpper
33
    error TicksMisordered(int24 tickLower, int24 tickUpper);
34

                            
                        
35
    /// @notice Thrown when tickLower is less than min tick
36
    /// @param tickLower The invalid tickLower
37
    error TickLowerOutOfBounds(int24 tickLower);
38

                            
                        
39
    /// @notice Thrown when tickUpper exceeds max tick
40
    /// @param tickUpper The invalid tickUpper
41
    error TickUpperOutOfBounds(int24 tickUpper);
42

                            
                        
43
    /// @notice For the tick spacing, the tick has too much liquidity
44
    error TickLiquidityOverflow(int24 tick);
45

                            
                        
46
    /// @notice Thrown when trying to initialize an already initialized pool
47
    error PoolAlreadyInitialized();
48

                            
                        
49
    /// @notice Thrown when trying to interact with a non-initialized pool
50
    error PoolNotInitialized();
51

                            
                        
52
    /// @notice Thrown when sqrtPriceLimitX96 on a swap has already exceeded its limit
53
    /// @param sqrtPriceCurrentX96 The invalid, already surpassed sqrtPriceLimitX96
54
    /// @param sqrtPriceLimitX96 The surpassed price limit
55
    error PriceLimitAlreadyExceeded(uint160 sqrtPriceCurrentX96, uint160 sqrtPriceLimitX96);
56

                            
                        
57
    /// @notice Thrown when sqrtPriceLimitX96 lies outside of valid tick/price range
58
    /// @param sqrtPriceLimitX96 The invalid, out-of-bounds sqrtPriceLimitX96
59
    error PriceLimitOutOfBounds(uint160 sqrtPriceLimitX96);
60

                            
                        
61
    /// @notice Thrown by donate if there is currently 0 liquidity, since the fees will not go to any liquidity providers
62
    error NoLiquidityToReceiveFees();
63

                            
                        
64
    /// @notice Thrown when trying to swap with max lp fee and specifying an output amount
65
    error InvalidFeeForExactOut();
66

                            
                        
67
    // info stored for each initialized individual tick
68
    struct TickInfo {
69
        // the total position liquidity that references this tick
70
        uint128 liquidityGross;
71
        // amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left),
72
        int128 liquidityNet;
73
        // fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick)
74
        // only has relative meaning, not absolute — the value depends on when the tick is initialized
75
        uint256 feeGrowthOutside0X128;
76
        uint256 feeGrowthOutside1X128;
77
    }
78

                            
                        
79
    /// @dev The state of a pool
80
    struct State {
81
        Slot0 slot0;
82
        uint256 feeGrowthGlobal0X128;
83
        uint256 feeGrowthGlobal1X128;
84
        uint128 liquidity;
85
        mapping(int24 => TickInfo) ticks;
86
        mapping(int16 => uint256) tickBitmap;
87
        mapping(bytes32 => Position.Info) positions;
88
    }
89

                            
                        
90
    /// @dev Common checks for valid tick inputs.
91
    function checkTicks(int24 tickLower, int24 tickUpper) private pure {
92
√ 2
⟳ 5
        if (tickLower >= tickUpper) TicksMisordered.selector.revertWith(tickLower, tickUpper);
93
√ 5
⟳ 5
        if (tickLower < TickMath.MIN_TICK) TickLowerOutOfBounds.selector.revertWith(tickLower);
94
√ 5
⟳ 5
        if (tickUpper > TickMath.MAX_TICK) TickUpperOutOfBounds.selector.revertWith(tickUpper);
95
    }
96

                            
                        
97
    function initialize(State storage self, uint160 sqrtPriceX96, uint24 protocolFee, uint24 lpFee)
98
        internal
99
√ 2
⟳ 2
        returns (int24 tick)
100
    {
101
√ 2
⟳ 3
        if (self.slot0.sqrtPriceX96() != 0) PoolAlreadyInitialized.selector.revertWith();
102

                            
                        
103
√ 2
⟳ 2
        tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96);
104

                            
                        
105
√ 3
⟳ 3
        self.slot0 = Slot0.wrap(bytes32(0)).setSqrtPriceX96(sqrtPriceX96).setTick(tick).setProtocolFee(protocolFee)
106
            .setLpFee(lpFee);
107
    }
108

                            
                        
109
    function setProtocolFee(State storage self, uint24 protocolFee) internal {
110
√ 1
⟳ 1
        self.checkPoolInitialized();
111
√ 2
⟳ 2
        self.slot0 = self.slot0.setProtocolFee(protocolFee);
112
    }
113

                            
                        
114
    /// @notice Only dynamic fee pools may update the lp fee.
115
    function setLPFee(State storage self, uint24 lpFee) internal {
116
        self.checkPoolInitialized();
117
        self.slot0 = self.slot0.setLpFee(lpFee);
118
    }
119

                            
                        
120
    struct ModifyLiquidityParams {
121
        // the address that owns the position
122
        address owner;
123
        // the lower and upper tick of the position
124
        int24 tickLower;
125
        int24 tickUpper;
126
        // any change in liquidity
127
        int128 liquidityDelta;
128
        // the spacing between ticks
129
        int24 tickSpacing;
130
        // used to distinguish positions of the same owner, at the same tick range
131
        bytes32 salt;
132
    }
133

                            
                        
134
    struct ModifyLiquidityState {
135
        bool flippedLower;
136
        uint128 liquidityGrossAfterLower;
137
        bool flippedUpper;
138
        uint128 liquidityGrossAfterUpper;
139
    }
140

                            
                        
141
    /// @notice Effect changes to a position in a pool
142
    /// @dev PoolManager checks that the pool is initialized before calling
143
    /// @param params the position details and the change to the position's liquidity to effect
144
    /// @return delta the deltas of the token balances of the pool, from the liquidity change
145
    /// @return feeDelta the fees generated by the liquidity range
146
    function modifyLiquidity(State storage self, ModifyLiquidityParams memory params)
147
        internal
148
√ 4
⟳ 4
        returns (BalanceDelta delta, BalanceDelta feeDelta)
149
    {
150
√ 6
⟳ 6
        int128 liquidityDelta = params.liquidityDelta;
151
√ 5
⟳ 5
        int24 tickLower = params.tickLower;
152
√ 5
⟳ 5
        int24 tickUpper = params.tickUpper;
153
√ 1
⟳ 1
        checkTicks(tickLower, tickUpper);
154

                            
                        
155
        {
156
            ModifyLiquidityState memory state;
157

                            
                        
158
            // if we need to update the ticks, do it
159
√ 2
⟳ 2
            if (liquidityDelta != 0) {
160
√ 3
⟳ 3
                (state.flippedLower, state.liquidityGrossAfterLower) =
161
√ 5
⟳ 5
                    updateTick(self, tickLower, liquidityDelta, false);
162
√ 11
⟳ 11
                (state.flippedUpper, state.liquidityGrossAfterUpper) = updateTick(self, tickUpper, liquidityDelta, true);
163

                            
                        
164
                // `>` and `>=` are logically equivalent here but `>=` is cheaper
165
√ 5
⟳ 5
                if (liquidityDelta >= 0) {
166
√ 2
⟳ 2
                    uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(params.tickSpacing);
167
√ 2
⟳ 2
                    if (state.liquidityGrossAfterLower > maxLiquidityPerTick) {
168
⟳ 2
                        TickLiquidityOverflow.selector.revertWith(tickLower);
169
                    }
170
√ 2
⟳ 2
                    if (state.liquidityGrossAfterUpper > maxLiquidityPerTick) {
171
⟳ 2
                        TickLiquidityOverflow.selector.revertWith(tickUpper);
172
                    }
173
                }
174

                            
                        
175
√ 2
⟳ 2
                if (state.flippedLower) {
176
√ 10
⟳ 10
                    self.tickBitmap.flipTick(tickLower, params.tickSpacing);
177
                }
178
√ 1
⟳ 1
                if (state.flippedUpper) {
179
√ 10
⟳ 10
                    self.tickBitmap.flipTick(tickUpper, params.tickSpacing);
180
                }
181
            }
182

                            
                        
183
            {
184
√ 2
⟳ 2
                (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) =
185
√ 4
⟳ 4
                    getFeeGrowthInside(self, tickLower, tickUpper);
186

                            
                        
187
√ 10
⟳ 10
                Position.Info storage position = self.positions.get(params.owner, tickLower, tickUpper, params.salt);
188
                (uint256 feesOwed0, uint256 feesOwed1) =
189
√ 2
⟳ 2
                    position.update(liquidityDelta, feeGrowthInside0X128, feeGrowthInside1X128);
190

                            
                        
191
                // Fees earned from LPing are calculated, and returned
192
√ 2
⟳ 2
                feeDelta = toBalanceDelta(feesOwed0.toInt128(), feesOwed1.toInt128());
193
            }
194

                            
                        
195
            // clear any tick data that is no longer needed
196
√ 2
⟳ 2
            if (liquidityDelta < 0) {
197
√ 2
                if (state.flippedLower) {
198
√ 1
                    clearTick(self, tickLower);
199
                }
200
√ 1
                if (state.flippedUpper) {
201
√ 1
⟳ 1
                    clearTick(self, tickUpper);
202
                }
203
            }
204
        }
205

                            
                        
206
√ 2
⟳ 2
        if (liquidityDelta != 0) {
207
√ 5
⟳ 5
            Slot0 _slot0 = self.slot0;
208
√ 2
⟳ 2
            (int24 tick, uint160 sqrtPriceX96) = (_slot0.tick(), _slot0.sqrtPriceX96());
209
√ 2
⟳ 2
            if (tick < tickLower) {
210
                // current tick is below the passed range; liquidity can only become in range by crossing from left to
211
                // right, when we'll need _more_ currency0 (it's becoming more valuable) so user must provide it
212
                delta = toBalanceDelta(
213
√ 1
⟳ 1
                    SqrtPriceMath.getAmount0Delta(
214
√ 5
⟳ 5
                        TickMath.getSqrtPriceAtTick(tickLower), TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta
215
                    ).toInt128(),
216
                    0
217
                );
218
√ 2
⟳ 2
            } else if (tick < tickUpper) {
219
                delta = toBalanceDelta(
220
√ 3
⟳ 3
                    SqrtPriceMath.getAmount0Delta(sqrtPriceX96, TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta)
221
                        .toInt128(),
222
√ 5
⟳ 5
                    SqrtPriceMath.getAmount1Delta(TickMath.getSqrtPriceAtTick(tickLower), sqrtPriceX96, liquidityDelta)
223
                        .toInt128()
224
                );
225

                            
                        
226
√ 11
⟳ 11
                self.liquidity = LiquidityMath.addDelta(self.liquidity, liquidityDelta);
227
            } else {
228
                // current tick is above the passed range; liquidity can only become in range by crossing from right to
229
                // left, when we'll need _more_ currency1 (it's becoming more valuable) so user must provide it
230
                delta = toBalanceDelta(
231
√ 1
⟳ 1
                    0,
232
√ 1
⟳ 1
                    SqrtPriceMath.getAmount1Delta(
233
√ 5
⟳ 5
                        TickMath.getSqrtPriceAtTick(tickLower), TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta
234
                    ).toInt128()
235
                );
236
            }
237
        }
238
    }
239

                            
                        
240
    // the top level state of the swap, the results of which are recorded in storage at the end
241
    struct SwapState {
242
        // the amount remaining to be swapped in/out of the input/output asset
243
        int256 amountSpecifiedRemaining;
244
        // the amount already swapped out/in of the output/input asset
245
        int256 amountCalculated;
246
        // current sqrt(price)
247
        uint160 sqrtPriceX96;
248
        // the tick associated with the current price
249
        int24 tick;
250
        // the global fee growth of the input token
251
        uint256 feeGrowthGlobalX128;
252
        // the current liquidity in range
253
        uint128 liquidity;
254
    }
255

                            
                        
256
    struct StepComputations {
257
        // the price at the beginning of the step
258
        uint160 sqrtPriceStartX96;
259
        // the next tick to swap to from the current tick in the swap direction
260
        int24 tickNext;
261
        // whether tickNext is initialized or not
262
        bool initialized;
263
        // sqrt(price) for the next tick (1/0)
264
        uint160 sqrtPriceNextX96;
265
        // how much is being swapped in in this step
266
        uint256 amountIn;
267
        // how much is being swapped out
268
        uint256 amountOut;
269
        // how much fee is being paid in
270
        uint256 feeAmount;
271
    }
272

                            
                        
273
    struct SwapParams {
274
        int24 tickSpacing;
275
        bool zeroForOne;
276
        int256 amountSpecified;
277
        uint160 sqrtPriceLimitX96;
278
        uint24 lpFeeOverride;
279
    }
280

                            
                        
281
    /// @notice Executes a swap against the state, and returns the amount deltas of the pool
282
    /// @dev PoolManager checks that the pool is initialized before calling
283
    function swap(State storage self, SwapParams memory params)
284
        internal
285
√ 5
⟳ 5
        returns (BalanceDelta result, uint256 feeForProtocol, uint24 swapFee, SwapState memory state)
286
    {
287
√ 3
⟳ 3
        Slot0 slot0Start = self.slot0;
288
√ 5
⟳ 5
        bool zeroForOne = params.zeroForOne;
289

                            
                        
290
√ 6
⟳ 6
        uint128 liquidityStart = self.liquidity;
291
        uint256 protocolFee =
292
√ 1
⟳ 1
            zeroForOne ? slot0Start.protocolFee().getZeroForOneFee() : slot0Start.protocolFee().getOneForZeroFee();
293

                            
                        
294
√ 6
⟳ 6
        state.amountSpecifiedRemaining = params.amountSpecified;
295
√ 3
⟳ 3
        state.amountCalculated = 0;
296
√ 3
⟳ 3
        state.sqrtPriceX96 = slot0Start.sqrtPriceX96();
297
√ 3
⟳ 3
        state.tick = slot0Start.tick();
298
√ 7
⟳ 7
        state.feeGrowthGlobalX128 = zeroForOne ? self.feeGrowthGlobal0X128 : self.feeGrowthGlobal1X128;
299
√ 3
⟳ 3
        state.liquidity = liquidityStart;
300

                            
                        
301
        // if the beforeSwap hook returned a valid fee override, use that as the LP fee, otherwise load from storage
302
        {
303
√ 3
⟳ 3
            uint24 lpFee = params.lpFeeOverride.isOverride()
304
                ? params.lpFeeOverride.removeOverrideFlagAndValidate()
305
                : slot0Start.lpFee();
306

                            
                        
307
√ 6
⟳ 6
            swapFee = protocolFee == 0 ? lpFee : uint16(protocolFee).calculateSwapFee(lpFee);
308
        }
309

                            
                        
310
√ 5
⟳ 5
        bool exactInput = params.amountSpecified < 0;
311

                            
                        
312
√ 5
⟳ 5
        if (swapFee == LPFeeLibrary.MAX_LP_FEE && !exactInput) {
313
⟳ 1
            InvalidFeeForExactOut.selector.revertWith();
314
        }
315

                            
                        
316
√ 2
⟳ 2
        if (params.amountSpecified == 0) return (BalanceDeltaLibrary.ZERO_DELTA, 0, swapFee, state);
317

                            
                        
318
√ 1
⟳ 1
        if (zeroForOne) {
319
√ 4
⟳ 4
            if (params.sqrtPriceLimitX96 >= slot0Start.sqrtPriceX96()) {
320
⟳ 7
                PriceLimitAlreadyExceeded.selector.revertWith(slot0Start.sqrtPriceX96(), params.sqrtPriceLimitX96);
321
            }
322
√ 1
⟳ 1
            if (params.sqrtPriceLimitX96 < TickMath.MIN_SQRT_PRICE) {
323
                PriceLimitOutOfBounds.selector.revertWith(params.sqrtPriceLimitX96);
324
            }
325
        } else {
326
√ 4
⟳ 4
            if (params.sqrtPriceLimitX96 <= slot0Start.sqrtPriceX96()) {
327
⟳ 1
                PriceLimitAlreadyExceeded.selector.revertWith(slot0Start.sqrtPriceX96(), params.sqrtPriceLimitX96);
328
            }
329
√ 1
⟳ 1
            if (params.sqrtPriceLimitX96 >= TickMath.MAX_SQRT_PRICE) {
330
                PriceLimitOutOfBounds.selector.revertWith(params.sqrtPriceLimitX96);
331
            }
332
        }
333

                            
                        
334
√ 396
⟳ 3
        StepComputations memory step;
335

                            
                        
336
        // continue swapping as long as we haven't used the entire input/output and haven't reached the price limit
337
√ 1582
⟳ 12
        while (!(state.amountSpecifiedRemaining == 0 || state.sqrtPriceX96 == params.sqrtPriceLimitX96)) {
338
√ 1580
⟳ 12
            step.sqrtPriceStartX96 = state.sqrtPriceX96;
339

                            
                        
340
√ 2370
⟳ 18
            (step.tickNext, step.initialized) =
341
√ 4345
⟳ 33
                self.tickBitmap.nextInitializedTickWithinOneWord(state.tick, params.tickSpacing, zeroForOne);
342

                            
                        
343
            // ensure that we do not overshoot the min/max tick, as the tick bitmap is not aware of these bounds
344
            if (step.tickNext <= TickMath.MIN_TICK) {
345
√ 3
⟳ 3
                step.tickNext = TickMath.MIN_TICK;
346
            }
347
√ 395
⟳ 3
            if (step.tickNext >= TickMath.MAX_TICK) {
348
√ 3
⟳ 3
                step.tickNext = TickMath.MAX_TICK;
349
            }
350

                            
                        
351
            // get the price for the next tick
352
√ 2370
⟳ 18
            step.sqrtPriceNextX96 = TickMath.getSqrtPriceAtTick(step.tickNext);
353

                            
                        
354
            // compute values to swap to the target tick, price limit, or point where input/output amount is exhausted
355
√ 5135
⟳ 39
            (state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep(
356
√ 2370
⟳ 18
                state.sqrtPriceX96,
357
√ 1580
⟳ 12
                SwapMath.getSqrtPriceTarget(zeroForOne, step.sqrtPriceNextX96, params.sqrtPriceLimitX96),
358
√ 1580
⟳ 12
                state.liquidity,
359
√ 790
⟳ 6
                state.amountSpecifiedRemaining,
360
√ 395
⟳ 3
                swapFee
361
            );
362

                            
                        
363
√ 395
⟳ 3
            if (!exactInput) {
364
                unchecked {
365
√ 3467
⟳ 6934
                    state.amountSpecifiedRemaining -= step.amountOut.toInt256();
366
                }
367
√ 31203
⟳ 62406
                state.amountCalculated -= (step.amountIn + step.feeAmount).toInt256();
368
            } else {
369
                // safe because we test that amountSpecified > amountIn + feeAmount in SwapMath
370
                unchecked {
371
√ 790
⟳ 6
                    state.amountSpecifiedRemaining += (step.amountIn + step.feeAmount).toInt256();
372
                }
373
√ 1975
⟳ 15
                state.amountCalculated += step.amountOut.toInt256();
374
            }
375

                            
                        
376
            // if the protocol fee is on, calculate how much is owed, decrement feeAmount, and increment protocolFee
377
√ 790
⟳ 6
            if (protocolFee > 0) {
378
                unchecked {
379
                    // step.amountIn does not include the swap fee, as it's already been taken from it,
380
                    // so add it back to get the total amountIn and use that to calculate the amount of fees owed to the protocol
381
                    // this line cannot overflow due to limits on the size of protocolFee and params.amountSpecified
382
√ 13868
⟳ 13868
                    uint256 delta = (step.amountIn + step.feeAmount) * protocolFee / ProtocolFeeLibrary.PIPS_DENOMINATOR;
383
                    // subtract it from the total fee and add it to the protocol fee
384
√ 10401
⟳ 10401
                    step.feeAmount -= delta;
385
√ 17335
⟳ 17335
                    feeForProtocol += delta;
386
                }
387
            }
388

                            
                        
389
            // update global fee tracker
390
√ 1580
⟳ 12
            if (state.liquidity > 0) {
391
                unchecked {
392
√ 2370
⟳ 9
                    state.feeGrowthGlobalX128 += FullMath.mulDiv(step.feeAmount, FixedPoint128.Q128, state.liquidity);
393
                }
394
            }
395

                            
                        
396
            // shift tick if we reached the next price
397
√ 790
⟳ 4
            if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {
398
                // if the tick is initialized, run the tick transition
399
√ 394
⟳ 2
                if (step.initialized) {
400
√ 3
⟳ 6
                    (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = zeroForOne
401
√ 2
⟳ 4
                        ? (state.feeGrowthGlobalX128, self.feeGrowthGlobal1X128)
402
√ 2
⟳ 4
                        : (self.feeGrowthGlobal0X128, state.feeGrowthGlobalX128);
403
√ 1
⟳ 2
                    int128 liquidityNet =
404
√ 4
⟳ 8
                        Pool.crossTick(self, step.tickNext, feeGrowthGlobal0X128, feeGrowthGlobal1X128);
405
                    // if we're moving leftward, we interpret liquidityNet as the opposite sign
406
                    // safe because liquidityNet cannot be type(int128).min
407
                    unchecked {
408
√ 3
⟳ 6
                        if (zeroForOne) liquidityNet = -liquidityNet;
409
                    }
410

                            
                        
411
√ 6
⟳ 12
                    state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet);
412
                }
413

                            
                        
414
                // Equivalent to `state.tick = zeroForOne ? step.tickNext - 1 : step.tickNext;`
415
                unchecked {
416
                    // cannot cast a bool to an int24 in Solidity
417
                    int24 _zeroForOne;
418
                    assembly ("memory-safe") {
419
√ 394
⟳ 2
                        _zeroForOne := and(zeroForOne, 0xff)
420
                    }
421
√ 2758
⟳ 14
                    state.tick = step.tickNext - _zeroForOne;
422
                }
423
√ 2
⟳ 2
            } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) {
424
                // recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved
425
√ 5
⟳ 5
                state.tick = TickMath.getTickAtSqrtPrice(state.sqrtPriceX96);
426
            }
427
        }
428

                            
                        
429
√ 3
⟳ 3
        self.slot0 = slot0Start.setTick(state.tick).setSqrtPriceX96(state.sqrtPriceX96);
430

                            
                        
431
        // update liquidity if it changed
432
√ 11
⟳ 11
        if (liquidityStart != state.liquidity) self.liquidity = state.liquidity;
433

                            
                        
434
        // update fee growth global
435
√ 1
⟳ 1
        if (!zeroForOne) {
436
√ 7
⟳ 7
            self.feeGrowthGlobal1X128 = state.feeGrowthGlobalX128;
437
        } else {
438
√ 7
⟳ 7
            self.feeGrowthGlobal0X128 = state.feeGrowthGlobalX128;
439
        }
440

                            
                        
441
        unchecked {
442
√ 2
⟳ 2
            if (zeroForOne != exactInput) {
443
                result = toBalanceDelta(
444
√ 1
⟳ 1
                    state.amountCalculated.toInt128(),
445
√ 2
⟳ 2
                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128()
446
                );
447
            } else {
448
                result = toBalanceDelta(
449
√ 2
⟳ 2
                    (params.amountSpecified - state.amountSpecifiedRemaining).toInt128(),
450
√ 1
⟳ 1
                    state.amountCalculated.toInt128()
451
                );
452
            }
453
        }
454
    }
455

                            
                        
456
    /// @notice Donates the given amount of currency0 and currency1 to the pool
457
√ 2
⟳ 2
    function donate(State storage state, uint256 amount0, uint256 amount1) internal returns (BalanceDelta delta) {
458
√ 6
⟳ 6
        uint128 liquidity = state.liquidity;
459
√ 3
⟳ 4
        if (liquidity == 0) NoLiquidityToReceiveFees.selector.revertWith();
460
        unchecked {
461
            // negation safe as amount0 and amount1 are always positive
462
√ 2
⟳ 2
            delta = toBalanceDelta(-(amount0.toInt128()), -(amount1.toInt128()));
463
√ 2
⟳ 2
            if (amount0 > 0) {
464
√ 6
⟳ 6
                state.feeGrowthGlobal0X128 += FullMath.mulDiv(amount0, FixedPoint128.Q128, liquidity);
465
            }
466
√ 2
⟳ 2
            if (amount1 > 0) {
467
√ 6
⟳ 6
                state.feeGrowthGlobal1X128 += FullMath.mulDiv(amount1, FixedPoint128.Q128, liquidity);
468
            }
469
        }
470
    }
471

                            
                        
472
    /// @notice Retrieves fee growth data
473
    /// @param self The Pool state struct
474
    /// @param tickLower The lower tick boundary of the position
475
    /// @param tickUpper The upper tick boundary of the position
476
    /// @return feeGrowthInside0X128 The all-time fee growth in token0, per unit of liquidity, inside the position's tick boundaries
477
    /// @return feeGrowthInside1X128 The all-time fee growth in token1, per unit of liquidity, inside the position's tick boundaries
478
    function getFeeGrowthInside(State storage self, int24 tickLower, int24 tickUpper)
479
        internal
480
        view
481
√ 5
⟳ 5
        returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128)
482
    {
483
√ 3
⟳ 3
        TickInfo storage lower = self.ticks[tickLower];
484
√ 10
⟳ 10
        TickInfo storage upper = self.ticks[tickUpper];
485
√ 2
⟳ 2
        int24 tickCurrent = self.slot0.tick();
486

                            
                        
487
        unchecked {
488
√ 2
⟳ 2
            if (tickCurrent < tickLower) {
489
√ 2
⟳ 2
                feeGrowthInside0X128 = lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
490
√ 2
⟳ 2
                feeGrowthInside1X128 = lower.feeGrowthOutside1X128 - upper.feeGrowthOutside1X128;
491
√ 2
⟳ 2
            } else if (tickCurrent >= tickUpper) {
492
√ 2
⟳ 2
                feeGrowthInside0X128 = upper.feeGrowthOutside0X128 - lower.feeGrowthOutside0X128;
493
√ 2
⟳ 2
                feeGrowthInside1X128 = upper.feeGrowthOutside1X128 - lower.feeGrowthOutside1X128;
494
            } else {
495
                feeGrowthInside0X128 =
496
√ 3
⟳ 3
                    self.feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128;
497
                feeGrowthInside1X128 =
498
√ 3
⟳ 3
                    self.feeGrowthGlobal1X128 - lower.feeGrowthOutside1X128 - upper.feeGrowthOutside1X128;
499
            }
500
        }
501
    }
502

                            
                        
503
    /// @notice Updates a tick and returns true if the tick was flipped from initialized to uninitialized, or vice versa
504
    /// @param self The mapping containing all tick information for initialized ticks
505
    /// @param tick The tick that will be updated
506
    /// @param liquidityDelta A new amount of liquidity to be added (subtracted) when tick is crossed from left to right (right to left)
507
    /// @param upper true for updating a position's upper tick, or false for updating a position's lower tick
508
    /// @return flipped Whether the tick was flipped from initialized to uninitialized, or vice versa
509
    /// @return liquidityGrossAfter The total amount of  liquidity for all positions that references the tick after the update
510
    function updateTick(State storage self, int24 tick, int128 liquidityDelta, bool upper)
511
        internal
512
√ 6
⟳ 6
        returns (bool flipped, uint128 liquidityGrossAfter)
513
    {
514
√ 6
⟳ 6
        TickInfo storage info = self.ticks[tick];
515

                            
                        
516
        uint128 liquidityGrossBefore;
517
        int128 liquidityNetBefore;
518
        assembly ("memory-safe") {
519
            // load first slot of info which contains liquidityGross and liquidityNet packed
520
            // where the top 128 bits are liquidityNet and the bottom 128 bits are liquidityGross
521
√ 4
⟳ 4
            let liquidity := sload(info.slot)
522
            // slice off top 128 bits of liquidity (liquidityNet) to get just liquidityGross
523
√ 2
⟳ 2
            liquidityGrossBefore := shr(128, shl(128, liquidity))
524
            // signed shift right 128 bits to get just liquidityNet
525
√ 2
⟳ 2
            liquidityNetBefore := sar(128, liquidity)
526
        }
527

                            
                        
528
√ 4
⟳ 4
        liquidityGrossAfter = LiquidityMath.addDelta(liquidityGrossBefore, liquidityDelta);
529

                            
                        
530
√ 10
⟳ 10
        flipped = (liquidityGrossAfter == 0) != (liquidityGrossBefore == 0);
531

                            
                        
532
√ 2
⟳ 2
        if (liquidityGrossBefore == 0) {
533
            // by convention, we assume that all growth before a tick was initialized happened _below_ the tick
534
√ 6
⟳ 6
            if (tick <= self.slot0.tick()) {
535
√ 8
⟳ 8
                info.feeGrowthOutside0X128 = self.feeGrowthGlobal0X128;
536
√ 8
⟳ 8
                info.feeGrowthOutside1X128 = self.feeGrowthGlobal1X128;
537
            }
538
        }
539

                            
                        
540
        // when the lower (upper) tick is crossed left to right (right to left), liquidity must be added (removed)
541
√ 8
⟳ 8
        int128 liquidityNet = upper ? liquidityNetBefore - liquidityDelta : liquidityNetBefore + liquidityDelta;
542
        assembly ("memory-safe") {
543
            // liquidityGrossAfter and liquidityNet are packed in the first slot of `info`
544
            // So we can store them with a single sstore by packing them ourselves first
545
            sstore(
546
√ 2
⟳ 2
                info.slot,
547
                // bitwise OR to pack liquidityGrossAfter and liquidityNet
548
                or(
549
                    // liquidityGross is in the low bits, upper bits are already 0
550
√ 4
⟳ 4
                    and(liquidityGrossAfter, 0xffffffffffffffffffffffffffffffff),
551
                    // shift liquidityNet to take the upper bits and lower bits get filled with 0
552
√ 4
⟳ 4
                    shl(128, liquidityNet)
553
                )
554
            )
555
        }
556
    }
557

                            
                        
558
    /// @notice Derives max liquidity per tick from given tick spacing
559
    /// @dev Executed within the pool constructor
560
    /// @param tickSpacing The amount of required tick separation, realized in multiples of `tickSpacing`
561
    ///     e.g., a tickSpacing of 3 requires ticks to be initialized every 3rd tick i.e., ..., -6, -3, 0, 3, 6, ...
562
    /// @return result The max liquidity per tick
563
    function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) internal pure returns (uint128 result) {
564
        // Equivalent to:
565
        // int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing;
566
        // int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing;
567
        // uint24 numTicks = uint24((maxTick - minTick) / tickSpacing) + 1;
568
        // return type(uint128).max / numTicks;
569
        int24 MAX_TICK = TickMath.MAX_TICK;
570
        int24 MIN_TICK = TickMath.MIN_TICK;
571
        // tick spacing will never be 0 since TickMath.MIN_TICK_SPACING is 1
572
        assembly ("memory-safe") {
573
√ 1
⟳ 1
            tickSpacing := signextend(2, tickSpacing)
574
√ 3
⟳ 3
            let minTick := mul(sdiv(MIN_TICK, tickSpacing), tickSpacing)
575
√ 3
⟳ 3
            let maxTick := mul(sdiv(MAX_TICK, tickSpacing), tickSpacing)
576
√ 2
⟳ 2
            let numTicks := add(sdiv(sub(maxTick, minTick), tickSpacing), 1)
577
√ 1
⟳ 1
            result := div(sub(shl(128, 1), 1), numTicks)
578
        }
579
    }
580

                            
                        
581
    /// @notice Reverts if the given pool has not been initialized
582
    function checkPoolInitialized(State storage self) internal view {
583
√ 3
⟳ 3
        if (self.slot0.sqrtPriceX96() == 0) PoolNotInitialized.selector.revertWith();
584
    }
585

                            
                        
586
    /// @notice Clears tick data
587
    /// @param self The mapping containing all initialized tick information for initialized ticks
588
    /// @param tick The tick that will be cleared
589
    function clearTick(State storage self, int24 tick) internal {
590
√ 6
        delete self.ticks[tick];
591
    }
592

                            
                        
593
    /// @notice Transitions to next tick as needed by price movement
594
    /// @param self The Pool state struct
595
    /// @param tick The destination tick of the transition
596
    /// @param feeGrowthGlobal0X128 The all-time global fee growth, per unit of liquidity, in token0
597
    /// @param feeGrowthGlobal1X128 The all-time global fee growth, per unit of liquidity, in token1
598
    /// @return liquidityNet The amount of liquidity added (subtracted) when tick is crossed from left to right (right to left)
599
    function crossTick(State storage self, int24 tick, uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128)
600
        internal
601
√ 1
⟳ 2
        returns (int128 liquidityNet)
602
    {
603
        unchecked {
604
√ 4
⟳ 8
            TickInfo storage info = self.ticks[tick];
605
√ 5
⟳ 10
            info.feeGrowthOutside0X128 = feeGrowthGlobal0X128 - info.feeGrowthOutside0X128;
606
√ 5
⟳ 10
            info.feeGrowthOutside1X128 = feeGrowthGlobal1X128 - info.feeGrowthOutside1X128;
607
√ 7
⟳ 14
            liquidityNet = info.liquidityNet;
608
        }
609
    }
610
}
611

                            
                        

Lines covered: 19 / 20 (95.0%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {FullMath} from "./FullMath.sol";
5
import {FixedPoint128} from "./FixedPoint128.sol";
6
import {LiquidityMath} from "./LiquidityMath.sol";
7
import {CustomRevert} from "./CustomRevert.sol";
8

                            
                        
9
/// @title Position
10
/// @notice Positions represent an owner address' liquidity between a lower and upper tick boundary
11
/// @dev Positions store additional state for tracking fees owed to the position
12
library Position {
13
    using CustomRevert for bytes4;
14

                            
                        
15
    /// @notice Cannot update a position with no liquidity
16
    error CannotUpdateEmptyPosition();
17

                            
                        
18
    // info stored for each user's position
19
    struct Info {
20
        // the amount of liquidity owned by this position
21
        uint128 liquidity;
22
        // fee growth per unit of liquidity as of the last update to liquidity or fees owed
23
        uint256 feeGrowthInside0LastX128;
24
        uint256 feeGrowthInside1LastX128;
25
    }
26

                            
                        
27
    /// @notice Returns the Info struct of a position, given an owner and position boundaries
28
    /// @param self The mapping containing all user positions
29
    /// @param owner The address of the position owner
30
    /// @param tickLower The lower tick boundary of the position
31
    /// @param tickUpper The upper tick boundary of the position
32
    /// @param salt A unique value to differentiate between multiple positions in the same range
33
    /// @return position The position info struct of the given owners' position
34
    function get(mapping(bytes32 => Info) storage self, address owner, int24 tickLower, int24 tickUpper, bytes32 salt)
35
        internal
36
        view
37
        returns (Info storage position)
38
    {
39
        // positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt))
40
        bytes32 positionKey;
41

                            
                        
42
        assembly ("memory-safe") {
43
√ 1
⟳ 1
            let fmp := mload(0x40)
44
√ 1
⟳ 1
            mstore(add(fmp, 0x26), salt) // [0x26, 0x46)
45
√ 3
⟳ 3
            mstore(add(fmp, 0x06), tickUpper) // [0x23, 0x26)
46
√ 1
⟳ 1
            mstore(add(fmp, 0x03), tickLower) // [0x20, 0x23)
47
√ 3
⟳ 3
            mstore(fmp, owner) // [0x0c, 0x20)
48
√ 2
⟳ 2
            positionKey := keccak256(add(fmp, 0x0c), 0x3a) // len is 58 bytes
49

                            
                        
50
            // now clean the memory we used
51
√ 3
⟳ 3
            mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt
52
√ 3
⟳ 3
            mstore(add(fmp, 0x20), 0) // fmp+0x20 held tickLower, tickUpper, salt
53
√ 4
⟳ 4
            mstore(fmp, 0) // fmp held owner
54
        }
55
√ 9
⟳ 9
        position = self[positionKey];
56
    }
57

                            
                        
58
    /// @notice Credits accumulated fees to a user's position
59
    /// @param self The individual position to update
60
    /// @param liquidityDelta The change in pool liquidity as a result of the position update
61
    /// @param feeGrowthInside0X128 The all-time fee growth in currency0, per unit of liquidity, inside the position's tick boundaries
62
    /// @param feeGrowthInside1X128 The all-time fee growth in currency1, per unit of liquidity, inside the position's tick boundaries
63
    /// @return feesOwed0 The amount of currency0 owed to the position owner
64
    /// @return feesOwed1 The amount of currency1 owed to the position owner
65
    function update(
66
        Info storage self,
67
        int128 liquidityDelta,
68
        uint256 feeGrowthInside0X128,
69
        uint256 feeGrowthInside1X128
70
√ 4
⟳ 4
    ) internal returns (uint256 feesOwed0, uint256 feesOwed1) {
71
√ 4
⟳ 4
        uint128 liquidity = self.liquidity;
72

                            
                        
73
√ 6
⟳ 6
        if (liquidityDelta == 0) {
74
            // disallow pokes for 0 liquidity positions
75
√ 2
⟳ 3
            if (liquidity == 0) CannotUpdateEmptyPosition.selector.revertWith();
76
        } else {
77
√ 3
⟳ 3
            self.liquidity = LiquidityMath.addDelta(liquidity, liquidityDelta);
78
        }
79

                            
                        
80
        // calculate accumulated fees. overflow in the subtraction of fee growth is expected
81
        unchecked {
82
            feesOwed0 =
83
√ 4
⟳ 4
                FullMath.mulDiv(feeGrowthInside0X128 - self.feeGrowthInside0LastX128, liquidity, FixedPoint128.Q128);
84
            feesOwed1 =
85
√ 4
⟳ 4
                FullMath.mulDiv(feeGrowthInside1X128 - self.feeGrowthInside1LastX128, liquidity, FixedPoint128.Q128);
86
        }
87

                            
                        
88
        // update the position
89
√ 3
⟳ 3
        self.feeGrowthInside0LastX128 = feeGrowthInside0X128;
90
√ 4
⟳ 4
        self.feeGrowthInside1LastX128 = feeGrowthInside1X128;
91
    }
92
}
93

                            
                        

Lines covered: 10 / 13 (76.9%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @notice library of functions related to protocol fees
5
library ProtocolFeeLibrary {
6
    /// @notice Max protocol fee is 0.1% (1000 pips)
7
    /// @dev Increasing these values could lead to overflow in Pool.swap
8
    uint16 public constant MAX_PROTOCOL_FEE = 1000;
9

                            
                        
10
    /// @notice Thresholds used for optimized bounds checks on protocol fees
11
    uint24 internal constant FEE_0_THRESHOLD = 1001;
12
    uint24 internal constant FEE_1_THRESHOLD = 1001 << 12;
13

                            
                        
14
    /// @notice the protocol fee is represented in hundredths of a bip
15
√ 3467
⟳ 3467
    uint256 internal constant PIPS_DENOMINATOR = 1_000_000;
16

                            
                        
17
    function getZeroForOneFee(uint24 self) internal pure returns (uint16) {
18
√ 1
⟳ 1
        return uint16(self & 0xfff);
19
    }
20

                            
                        
21
    function getOneForZeroFee(uint24 self) internal pure returns (uint16) {
22
√ 6
⟳ 6
        return uint16(self >> 12);
23
    }
24

                            
                        
25
    function isValidProtocolFee(uint24 self) internal pure returns (bool valid) {
26
        // Equivalent to: getZeroForOneFee(self) <= MAX_PROTOCOL_FEE && getOneForZeroFee(self) <= MAX_PROTOCOL_FEE
27
        assembly ("memory-safe") {
28
√ 4
⟳ 4
            let isZeroForOneFeeOk := lt(and(self, 0xfff), FEE_0_THRESHOLD)
29
√ 4
⟳ 4
            let isOneForZeroFeeOk := lt(and(self, 0xfff000), FEE_1_THRESHOLD)
30
√ 2
⟳ 2
            valid := and(isZeroForOneFeeOk, isOneForZeroFeeOk)
31
        }
32
    }
33

                            
                        
34
    // The protocol fee is taken from the input amount first and then the LP fee is taken from the remaining
35
    // The swap fee is capped at 100%
36
    // Equivalent to protocolFee + lpFee(1_000_000 - protocolFee) / 1_000_000
37
    /// @dev here `self` is just a single direction's protocol fee, not a packed type of 2 protocol fees
38
    function calculateSwapFee(uint16 self, uint24 lpFee) internal pure returns (uint24 swapFee) {
39
        // protocolFee + lpFee - (protocolFee * lpFee / 1_000_000). Div rounds up to favor LPs over the protocol.
40
        assembly ("memory-safe") {
41
            self := and(self, 0xffff)
42
√ 1
⟳ 1
            lpFee := and(lpFee, 0xffffff)
43
√ 3
⟳ 3
            let numerator := mul(self, lpFee)
44
√ 4
⟳ 4
            let divRoundingUp := add(div(numerator, PIPS_DENOMINATOR), gt(mod(numerator, PIPS_DENOMINATOR), 0))
45
√ 2
⟳ 2
            swapFee := sub(add(self, lpFee), divRoundingUp)
46
        }
47
    }
48
}
49

                            
                        

Lines covered: 10 / 13 (76.9%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {CustomRevert} from "./CustomRevert.sol";
5

                            
                        
6
/// @title Safe casting methods
7
/// @notice Contains methods for safely casting between types
8
library SafeCast {
9
    using CustomRevert for bytes4;
10

                            
                        
11
    error SafeCastOverflow();
12

                            
                        
13
    /// @notice Cast a uint256 to a uint160, revert on overflow
14
    /// @param x The uint256 to be downcasted
15
    /// @return y The downcasted integer, now type uint160
16
    function toUint160(uint256 x) internal pure returns (uint160 y) {
17
√ 1
⟳ 1
        y = uint160(x);
18
√ 5
⟳ 5
        if (y != x) SafeCastOverflow.selector.revertWith();
19
    }
20

                            
                        
21
    /// @notice Cast a uint256 to a uint128, revert on overflow
22
    /// @param x The uint256 to be downcasted
23
    /// @return y The downcasted integer, now type uint128
24
    function toUint128(uint256 x) internal pure returns (uint128 y) {
25
        y = uint128(x);
26
        if (x != y) SafeCastOverflow.selector.revertWith();
27
    }
28

                            
                        
29
    /// @notice Cast a int256 to a int128, revert on overflow or underflow
30
    /// @param x The int256 to be downcasted
31
    /// @return y The downcasted integer, now type int128
32
    function toInt128(int256 x) internal pure returns (int128 y) {
33
√ 5
⟳ 5
        y = int128(x);
34
√ 30
⟳ 31
        if (y != x) SafeCastOverflow.selector.revertWith();
35
    }
36

                            
                        
37
    /// @notice Cast a uint256 to a int256, revert on overflow
38
    /// @param x The uint256 to be casted
39
    /// @return y The casted integer, now type int256
40
√ 2
⟳ 2
    function toInt256(uint256 x) internal pure returns (int256 y) {
41
√ 2
⟳ 2
        y = int256(x);
42
√ 4
⟳ 4
        if (y < 0) SafeCastOverflow.selector.revertWith();
43
    }
44

                            
                        
45
    /// @notice Cast a uint256 to a int128, revert on overflow
46
    /// @param x The uint256 to be downcasted
47
    /// @return The downcasted integer, now type int128
48
√ 1
⟳ 1
    function toInt128(uint256 x) internal pure returns (int128) {
49
√ 2
⟳ 3
        if (x >= 1 << 127) SafeCastOverflow.selector.revertWith();
50
√ 1
⟳ 1
        return int128(int256(x));
51
    }
52
}
53

                            
                        

Lines covered: 59 / 73 (80.8%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {SafeCast} from "./SafeCast.sol";
5

                            
                        
6
import {FullMath} from "./FullMath.sol";
7
import {UnsafeMath} from "./UnsafeMath.sol";
8
import {FixedPoint96} from "./FixedPoint96.sol";
9

                            
                        
10
/// @title Functions based on Q64.96 sqrt price and liquidity
11
/// @notice Contains the math that uses square root of price as a Q64.96 and liquidity to compute deltas
12
library SqrtPriceMath {
13
    using SafeCast for uint256;
14

                            
                        
15
    error InvalidPriceOrLiquidity();
16
    error InvalidPrice();
17
    error NotEnoughLiquidity();
18
    error PriceOverflow();
19

                            
                        
20
    /// @notice Gets the next sqrt price given a delta of currency0
21
    /// @dev Always rounds up, because in the exact output case (increasing price) we need to move the price at least
22
    /// far enough to get the desired output amount, and in the exact input case (decreasing price) we need to move the
23
    /// price less in order to not send too much output.
24
    /// The most precise formula for this is liquidity * sqrtPX96 / (liquidity +- amount * sqrtPX96),
25
    /// if this is impossible because of overflow, we calculate liquidity / (liquidity / sqrtPX96 +- amount).
26
    /// @param sqrtPX96 The starting price, i.e. before accounting for the currency0 delta
27
    /// @param liquidity The amount of usable liquidity
28
    /// @param amount How much of currency0 to add or remove from virtual reserves
29
    /// @param add Whether to add or remove the amount of currency0
30
    /// @return The price after adding or removing amount, depending on add
31
    function getNextSqrtPriceFromAmount0RoundingUp(uint160 sqrtPX96, uint128 liquidity, uint256 amount, bool add)
32
        internal
33
        pure
34
√ 1
⟳ 1
        returns (uint160)
35
    {
36
        // we short circuit amount == 0 because the result is otherwise not guaranteed to equal the input price
37
√ 3
⟳ 3
        if (amount == 0) return sqrtPX96;
38
√ 5
⟳ 5
        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;
39

                            
                        
40
        if (add) {
41
            unchecked {
42
√ 2
⟳ 2
                uint256 product = amount * sqrtPX96;
43
√ 4
⟳ 4
                if (product / amount == sqrtPX96) {
44
√ 3
⟳ 3
                    uint256 denominator = numerator1 + product;
45
√ 3
⟳ 3
                    if (denominator >= numerator1) {
46
                        // always fits in 160 bits
47
√ 4
⟳ 4
                        return uint160(FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator));
48
                    }
49
                }
50
            }
51
            // denominator is checked for overflow
52
            return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96) + amount));
53
        } else {
54
            unchecked {
55
√ 7
⟳ 7
                uint256 product = amount * sqrtPX96;
56
                // if the product overflows, we know the denominator underflows
57
                // in addition, we must check that the denominator does not underflow
58
                // equivalent: if (product / amount != sqrtPX96 || numerator1 <= product) revert PriceOverflow();
59
                assembly ("memory-safe") {
60
                    if iszero(
61
                        and(
62
√ 3
⟳ 3
                            eq(div(product, amount), and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)),
63
√ 3
⟳ 3
                            gt(numerator1, product)
64
                        )
65
                    ) {
66
                        mstore(0, 0xf5c787f1) // selector for PriceOverflow()
67
                        revert(0x1c, 0x04)
68
                    }
69
                }
70
√ 1
⟳ 1
                uint256 denominator = numerator1 - product;
71
√ 1
⟳ 1
                return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator).toUint160();
72
            }
73
        }
74
    }
75

                            
                        
76
    /// @notice Gets the next sqrt price given a delta of currency1
77
    /// @dev Always rounds down, because in the exact output case (decreasing price) we need to move the price at least
78
    /// far enough to get the desired output amount, and in the exact input case (increasing price) we need to move the
79
    /// price less in order to not send too much output.
80
    /// The formula we compute is within <1 wei of the lossless version: sqrtPX96 +- amount / liquidity
81
    /// @param sqrtPX96 The starting price, i.e., before accounting for the currency1 delta
82
    /// @param liquidity The amount of usable liquidity
83
    /// @param amount How much of currency1 to add, or remove, from virtual reserves
84
    /// @param add Whether to add, or remove, the amount of currency1
85
    /// @return The price after adding or removing `amount`
86
    function getNextSqrtPriceFromAmount1RoundingDown(uint160 sqrtPX96, uint128 liquidity, uint256 amount, bool add)
87
        internal
88
        pure
89
√ 1
⟳ 1
        returns (uint160)
90
    {
91
        // if we're adding (subtracting), rounding down requires rounding the quotient down (up)
92
        // in both cases, avoid a mulDiv for most inputs
93
√ 1
⟳ 1
        if (add) {
94
√ 1
⟳ 1
            uint256 quotient = (
95
√ 1
⟳ 1
                amount <= type(uint160).max
96
√ 3
⟳ 3
                    ? (amount << FixedPoint96.RESOLUTION) / liquidity
97
                    : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity)
98
            );
99

                            
                        
100
√ 3
⟳ 3
            return (uint256(sqrtPX96) + quotient).toUint160();
101
        } else {
102
√ 1
⟳ 1
            uint256 quotient = (
103
√ 1
⟳ 1
                amount <= type(uint160).max
104
√ 3
⟳ 3
                    ? UnsafeMath.divRoundingUp(amount << FixedPoint96.RESOLUTION, liquidity)
105
                    : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity)
106
            );
107

                            
                        
108
            // equivalent: if (sqrtPX96 <= quotient) revert NotEnoughLiquidity();
109
            assembly ("memory-safe") {
110
√ 3
⟳ 3
                if iszero(gt(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff), quotient)) {
111
                    mstore(0, 0x4323a555) // selector for NotEnoughLiquidity()
112
                    revert(0x1c, 0x04)
113
                }
114
            }
115
            // always fits 160 bits
116
            unchecked {
117
√ 5
⟳ 5
                return uint160(sqrtPX96 - quotient);
118
            }
119
        }
120
    }
121

                            
                        
122
    /// @notice Gets the next sqrt price given an input amount of currency0 or currency1
123
    /// @dev Throws if price or liquidity are 0, or if the next price is out of bounds
124
    /// @param sqrtPX96 The starting price, i.e., before accounting for the input amount
125
    /// @param liquidity The amount of usable liquidity
126
    /// @param amountIn How much of currency0, or currency1, is being swapped in
127
    /// @param zeroForOne Whether the amount in is currency0 or currency1
128
    /// @return uint160 The price after adding the input amount to currency0 or currency1
129
    function getNextSqrtPriceFromInput(uint160 sqrtPX96, uint128 liquidity, uint256 amountIn, bool zeroForOne)
130
        internal
131
        pure
132
√ 1
⟳ 1
        returns (uint160)
133
    {
134
        // equivalent: if (sqrtPX96 == 0 || liquidity == 0) revert InvalidPriceOrLiquidity();
135
        assembly ("memory-safe") {
136
            if or(
137
√ 2
⟳ 2
                iszero(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)),
138
√ 2
⟳ 2
                iszero(and(liquidity, 0xffffffffffffffffffffffffffffffff))
139
            ) {
140
                mstore(0, 0x4f2461b8) // selector for InvalidPriceOrLiquidity()
141
                revert(0x1c, 0x04)
142
            }
143
        }
144

                            
                        
145
        // round to make sure that we don't pass the target price
146
√ 1
⟳ 1
        return zeroForOne
147
√ 5
⟳ 5
            ? getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true)
148
√ 5
⟳ 5
            : getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true);
149
    }
150

                            
                        
151
    /// @notice Gets the next sqrt price given an output amount of currency0 or currency1
152
    /// @dev Throws if price or liquidity are 0 or the next price is out of bounds
153
    /// @param sqrtPX96 The starting price before accounting for the output amount
154
    /// @param liquidity The amount of usable liquidity
155
    /// @param amountOut How much of currency0, or currency1, is being swapped out
156
    /// @param zeroForOne Whether the amount out is currency1 or currency0
157
    /// @return uint160 The price after removing the output amount of currency0 or currency1
158
    function getNextSqrtPriceFromOutput(uint160 sqrtPX96, uint128 liquidity, uint256 amountOut, bool zeroForOne)
159
        internal
160
        pure
161
√ 1
⟳ 1
        returns (uint160)
162
    {
163
        // equivalent: if (sqrtPX96 == 0 || liquidity == 0) revert InvalidPriceOrLiquidity();
164
        assembly ("memory-safe") {
165
            if or(
166
√ 2
⟳ 2
                iszero(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)),
167
√ 2
⟳ 2
                iszero(and(liquidity, 0xffffffffffffffffffffffffffffffff))
168
            ) {
169
                mstore(0, 0x4f2461b8) // selector for InvalidPriceOrLiquidity()
170
                revert(0x1c, 0x04)
171
            }
172
        }
173

                            
                        
174
        // round to make sure that we pass the target price
175
√ 1
⟳ 1
        return zeroForOne
176
√ 4
⟳ 4
            ? getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false)
177
√ 5
⟳ 5
            : getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false);
178
    }
179

                            
                        
180
    /// @notice Gets the amount0 delta between two prices
181
    /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper),
182
    /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower))
183
    /// @param sqrtPriceAX96 A sqrt price
184
    /// @param sqrtPriceBX96 Another sqrt price
185
    /// @param liquidity The amount of usable liquidity
186
    /// @param roundUp Whether to round the amount up or down
187
    /// @return uint256 Amount of currency0 required to cover a position of size liquidity between the two passed prices
188
    function getAmount0Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity, bool roundUp)
189
        internal
190
        pure
191
√ 1
⟳ 1
        returns (uint256)
192
    {
193
        unchecked {
194
√ 2
⟳ 2
            if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
195

                            
                        
196
            // equivalent: if (sqrtPriceAX96 == 0) revert InvalidPrice();
197
            assembly ("memory-safe") {
198
√ 2
⟳ 2
                if iszero(and(sqrtPriceAX96, 0xffffffffffffffffffffffffffffffffffffffff)) {
199
                    mstore(0, 0x00bfc921) // selector for InvalidPrice()
200
                    revert(0x1c, 0x04)
201
                }
202
            }
203

                            
                        
204
√ 5
⟳ 5
            uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;
205
√ 3
⟳ 3
            uint256 numerator2 = sqrtPriceBX96 - sqrtPriceAX96;
206

                            
                        
207
√ 1
⟳ 1
            return roundUp
208
√ 5
⟳ 5
                ? UnsafeMath.divRoundingUp(FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtPriceBX96), sqrtPriceAX96)
209
√ 1975
⟳ 34670
                : FullMath.mulDiv(numerator1, numerator2, sqrtPriceBX96) / sqrtPriceAX96;
210
        }
211
    }
212

                            
                        
213
    /// @notice Equivalent to: `a >= b ? a - b : b - a`
214
    function absDiff(uint160 a, uint160 b) internal pure returns (uint256 res) {
215
        assembly ("memory-safe") {
216
            let diff :=
217
√ 4
⟳ 4
                sub(and(a, 0xffffffffffffffffffffffffffffffffffffffff), and(b, 0xffffffffffffffffffffffffffffffffffffffff))
218
            // mask = 0 if a >= b else -1 (all 1s)
219
√ 1
⟳ 1
            let mask := sar(255, diff)
220
            // if a >= b, res = a - b = 0 ^ (a - b)
221
            // if a < b, res = b - a = ~~(b - a) = ~(-(b - a) - 1) = ~(a - b - 1) = (-1) ^ (a - b - 1)
222
            // either way, res = mask ^ (a - b + mask)
223
√ 3
⟳ 3
            res := xor(mask, add(mask, diff))
224
        }
225
    }
226

                            
                        
227
    /// @notice Gets the amount1 delta between two prices
228
    /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower))
229
    /// @param sqrtPriceAX96 A sqrt price
230
    /// @param sqrtPriceBX96 Another sqrt price
231
    /// @param liquidity The amount of usable liquidity
232
    /// @param roundUp Whether to round the amount up, or down
233
    /// @return amount1 Amount of currency1 required to cover a position of size liquidity between the two passed prices
234
    function getAmount1Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity, bool roundUp)
235
        internal
236
        pure
237
√ 1
⟳ 1
        returns (uint256 amount1)
238
    {
239
        uint256 numerator = absDiff(sqrtPriceAX96, sqrtPriceBX96);
240
        uint256 denominator = FixedPoint96.Q96;
241
        uint256 _liquidity;
242
        assembly ("memory-safe") {
243
            // avoid implicit upcasting
244
√ 1
⟳ 1
            _liquidity := and(liquidity, 0xffffffffffffffffffffffffffffffff)
245
        }
246
        /**
247
         * Equivalent to:
248
         *   amount1 = roundUp
249
         *       ? FullMath.mulDivRoundingUp(liquidity, sqrtPriceBX96 - sqrtPriceAX96, FixedPoint96.Q96)
250
         *       : FullMath.mulDiv(liquidity, sqrtPriceBX96 - sqrtPriceAX96, FixedPoint96.Q96);
251
         * Cannot overflow because `type(uint128).max * type(uint160).max >> 96 < (1 << 192)`.
252
         */
253
√ 1
⟳ 1
        amount1 = FullMath.mulDiv(_liquidity, numerator, denominator);
254
        assembly ("memory-safe") {
255
√ 6
⟳ 6
            amount1 := add(amount1, and(gt(mulmod(_liquidity, numerator, denominator), 0), roundUp))
256
        }
257
    }
258

                            
                        
259
    /// @notice Helper that gets signed currency0 delta
260
    /// @param sqrtPriceAX96 A sqrt price
261
    /// @param sqrtPriceBX96 Another sqrt price
262
    /// @param liquidity The change in liquidity for which to compute the amount0 delta
263
    /// @return int256 Amount of currency0 corresponding to the passed liquidityDelta between the two prices
264
    function getAmount0Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, int128 liquidity)
265
        internal
266
        pure
267
√ 1
⟳ 1
        returns (int256)
268
    {
269
        unchecked {
270
√ 2
⟳ 2
            return liquidity < 0
271
√ 5
                ? getAmount0Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(-liquidity), false).toInt256()
272
√ 5
⟳ 5
                : -getAmount0Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(liquidity), true).toInt256();
273
        }
274
    }
275

                            
                        
276
    /// @notice Helper that gets signed currency1 delta
277
    /// @param sqrtPriceAX96 A sqrt price
278
    /// @param sqrtPriceBX96 Another sqrt price
279
    /// @param liquidity The change in liquidity for which to compute the amount1 delta
280
    /// @return int256 Amount of currency1 corresponding to the passed liquidityDelta between the two prices
281
    function getAmount1Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, int128 liquidity)
282
        internal
283
        pure
284
√ 1
⟳ 1
        returns (int256)
285
    {
286
        unchecked {
287
√ 2
⟳ 2
            return liquidity < 0
288
√ 5
                ? getAmount1Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(-liquidity), false).toInt256()
289
√ 5
⟳ 5
                : -getAmount1Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(liquidity), true).toInt256();
290
        }
291
    }
292
}
293

                            
                        

Lines covered: 0 / 96 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {PoolId} from "../types/PoolId.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {Position} from "./Position.sol";
7

                            
                        
8
/// @notice A helper library to provide state getters that use extsload
9
library StateLibrary {
10
    /// @notice index of pools mapping in the PoolManager
11
    bytes32 public constant POOLS_SLOT = bytes32(uint256(6));
12

                            
                        
13
    /// @notice index of feeGrowthGlobal0X128 in Pool.State
14
    uint256 public constant FEE_GROWTH_GLOBAL0_OFFSET = 1;
15
    /// @notice index of feeGrowthGlobal1X128 in Pool.State
16
    uint256 public constant FEE_GROWTH_GLOBAL1_OFFSET = 2;
17

                            
                        
18
    /// @notice index of liquidity in Pool.State
19
    uint256 public constant LIQUIDITY_OFFSET = 3;
20

                            
                        
21
    /// @notice index of TicksInfo mapping in Pool.State: mapping(int24 => TickInfo) ticks;
22
    uint256 public constant TICKS_OFFSET = 4;
23

                            
                        
24
    /// @notice index of tickBitmap mapping in Pool.State
25
    uint256 public constant TICK_BITMAP_OFFSET = 5;
26

                            
                        
27
    /// @notice index of Position.Info mapping in Pool.State: mapping(bytes32 => Position.Info) positions;
28
    uint256 public constant POSITIONS_OFFSET = 6;
29

                            
                        
30
    /**
31
     * @notice Get Slot0 of the pool: sqrtPriceX96, tick, protocolFee, lpFee
32
     * @dev Corresponds to pools[poolId].slot0
33
     * @param manager The pool manager contract.
34
     * @param poolId The ID of the pool.
35
     * @return sqrtPriceX96 The square root of the price of the pool, in Q96 precision.
36
     * @return tick The current tick of the pool.
37
     * @return protocolFee The protocol fee of the pool.
38
     * @return lpFee The swap fee of the pool.
39
     */
40
    function getSlot0(IPoolManager manager, PoolId poolId)
41
        internal
42
        view
43
        returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee)
44
    {
45
        // slot key of Pool.State value: `pools[poolId]`
46
        bytes32 stateSlot = _getPoolStateSlot(poolId);
47

                            
                        
48
        bytes32 data = manager.extsload(stateSlot);
49

                            
                        
50
        //   24 bits  |24bits|24bits      |24 bits|160 bits
51
        // 0x000000   |000bb8|000000      |ffff75 |0000000000000000fe3aa841ba359daa0ea9eff7
52
        // ---------- | fee  |protocolfee | tick  | sqrtPriceX96
53
        assembly ("memory-safe") {
54
            // bottom 160 bits of data
55
            sqrtPriceX96 := and(data, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
56
            // next 24 bits of data
57
            tick := signextend(2, shr(160, data))
58
            // next 24 bits of data
59
            protocolFee := and(shr(184, data), 0xFFFFFF)
60
            // last 24 bits of data
61
            lpFee := and(shr(208, data), 0xFFFFFF)
62
        }
63
    }
64

                            
                        
65
    /**
66
     * @notice Retrieves the tick information of a pool at a specific tick.
67
     * @dev Corresponds to pools[poolId].ticks[tick]
68
     * @param manager The pool manager contract.
69
     * @param poolId The ID of the pool.
70
     * @param tick The tick to retrieve information for.
71
     * @return liquidityGross The total position liquidity that references this tick
72
     * @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left)
73
     * @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick)
74
     * @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick)
75
     */
76
    function getTickInfo(IPoolManager manager, PoolId poolId, int24 tick)
77
        internal
78
        view
79
        returns (
80
            uint128 liquidityGross,
81
            int128 liquidityNet,
82
            uint256 feeGrowthOutside0X128,
83
            uint256 feeGrowthOutside1X128
84
        )
85
    {
86
        bytes32 slot = _getTickInfoSlot(poolId, tick);
87

                            
                        
88
        // read all 3 words of the TickInfo struct
89
        bytes32[] memory data = manager.extsload(slot, 3);
90
        assembly ("memory-safe") {
91
            let firstWord := mload(add(data, 32))
92
            liquidityNet := sar(128, firstWord)
93
            liquidityGross := and(firstWord, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
94
            feeGrowthOutside0X128 := mload(add(data, 64))
95
            feeGrowthOutside1X128 := mload(add(data, 96))
96
        }
97
    }
98

                            
                        
99
    /**
100
     * @notice Retrieves the liquidity information of a pool at a specific tick.
101
     * @dev Corresponds to pools[poolId].ticks[tick].liquidityGross and pools[poolId].ticks[tick].liquidityNet. A more gas efficient version of getTickInfo
102
     * @param manager The pool manager contract.
103
     * @param poolId The ID of the pool.
104
     * @param tick The tick to retrieve liquidity for.
105
     * @return liquidityGross The total position liquidity that references this tick
106
     * @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left)
107
     */
108
    function getTickLiquidity(IPoolManager manager, PoolId poolId, int24 tick)
109
        internal
110
        view
111
        returns (uint128 liquidityGross, int128 liquidityNet)
112
    {
113
        bytes32 slot = _getTickInfoSlot(poolId, tick);
114

                            
                        
115
        bytes32 value = manager.extsload(slot);
116
        assembly ("memory-safe") {
117
            liquidityNet := sar(128, value)
118
            liquidityGross := and(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
119
        }
120
    }
121

                            
                        
122
    /**
123
     * @notice Retrieves the fee growth outside a tick range of a pool
124
     * @dev Corresponds to pools[poolId].ticks[tick].feeGrowthOutside0X128 and pools[poolId].ticks[tick].feeGrowthOutside1X128. A more gas efficient version of getTickInfo
125
     * @param manager The pool manager contract.
126
     * @param poolId The ID of the pool.
127
     * @param tick The tick to retrieve fee growth for.
128
     * @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick)
129
     * @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick)
130
     */
131
    function getTickFeeGrowthOutside(IPoolManager manager, PoolId poolId, int24 tick)
132
        internal
133
        view
134
        returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128)
135
    {
136
        bytes32 slot = _getTickInfoSlot(poolId, tick);
137

                            
                        
138
        // offset by 1 word, since the first word is liquidityGross + liquidityNet
139
        bytes32[] memory data = manager.extsload(bytes32(uint256(slot) + 1), 2);
140
        assembly ("memory-safe") {
141
            feeGrowthOutside0X128 := mload(add(data, 32))
142
            feeGrowthOutside1X128 := mload(add(data, 64))
143
        }
144
    }
145

                            
                        
146
    /**
147
     * @notice Retrieves the global fee growth of a pool.
148
     * @dev Corresponds to pools[poolId].feeGrowthGlobal0X128 and pools[poolId].feeGrowthGlobal1X128
149
     * @param manager The pool manager contract.
150
     * @param poolId The ID of the pool.
151
     * @return feeGrowthGlobal0 The global fee growth for token0.
152
     * @return feeGrowthGlobal1 The global fee growth for token1.
153
     */
154
    function getFeeGrowthGlobals(IPoolManager manager, PoolId poolId)
155
        internal
156
        view
157
        returns (uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1)
158
    {
159
        // slot key of Pool.State value: `pools[poolId]`
160
        bytes32 stateSlot = _getPoolStateSlot(poolId);
161

                            
                        
162
        // Pool.State, `uint256 feeGrowthGlobal0X128`
163
        bytes32 slot_feeGrowthGlobal0X128 = bytes32(uint256(stateSlot) + FEE_GROWTH_GLOBAL0_OFFSET);
164

                            
                        
165
        // read the 2 words of feeGrowthGlobal
166
        bytes32[] memory data = manager.extsload(slot_feeGrowthGlobal0X128, 2);
167
        assembly ("memory-safe") {
168
            feeGrowthGlobal0 := mload(add(data, 32))
169
            feeGrowthGlobal1 := mload(add(data, 64))
170
        }
171
    }
172

                            
                        
173
    /**
174
     * @notice Retrieves total the liquidity of a pool.
175
     * @dev Corresponds to pools[poolId].liquidity
176
     * @param manager The pool manager contract.
177
     * @param poolId The ID of the pool.
178
     * @return liquidity The liquidity of the pool.
179
     */
180
    function getLiquidity(IPoolManager manager, PoolId poolId) internal view returns (uint128 liquidity) {
181
        // slot key of Pool.State value: `pools[poolId]`
182
        bytes32 stateSlot = _getPoolStateSlot(poolId);
183

                            
                        
184
        // Pool.State: `uint128 liquidity`
185
        bytes32 slot = bytes32(uint256(stateSlot) + LIQUIDITY_OFFSET);
186

                            
                        
187
        liquidity = uint128(uint256(manager.extsload(slot)));
188
    }
189

                            
                        
190
    /**
191
     * @notice Retrieves the tick bitmap of a pool at a specific tick.
192
     * @dev Corresponds to pools[poolId].tickBitmap[tick]
193
     * @param manager The pool manager contract.
194
     * @param poolId The ID of the pool.
195
     * @param tick The tick to retrieve the bitmap for.
196
     * @return tickBitmap The bitmap of the tick.
197
     */
198
    function getTickBitmap(IPoolManager manager, PoolId poolId, int16 tick)
199
        internal
200
        view
201
        returns (uint256 tickBitmap)
202
    {
203
        // slot key of Pool.State value: `pools[poolId]`
204
        bytes32 stateSlot = _getPoolStateSlot(poolId);
205

                            
                        
206
        // Pool.State: `mapping(int16 => uint256) tickBitmap;`
207
        bytes32 tickBitmapMapping = bytes32(uint256(stateSlot) + TICK_BITMAP_OFFSET);
208

                            
                        
209
        // slot id of the mapping key: `pools[poolId].tickBitmap[tick]
210
        bytes32 slot = keccak256(abi.encodePacked(int256(tick), tickBitmapMapping));
211

                            
                        
212
        tickBitmap = uint256(manager.extsload(slot));
213
    }
214

                            
                        
215
    /**
216
     * @notice Retrieves the position information of a pool at a specific position ID.
217
     * @dev Corresponds to pools[poolId].positions[positionId]
218
     * @param manager The pool manager contract.
219
     * @param poolId The ID of the pool.
220
     * @param positionId The ID of the position.
221
     * @return liquidity The liquidity of the position.
222
     * @return feeGrowthInside0LastX128 The fee growth inside the position for token0.
223
     * @return feeGrowthInside1LastX128 The fee growth inside the position for token1.
224
     */
225
    function getPositionInfo(IPoolManager manager, PoolId poolId, bytes32 positionId)
226
        internal
227
        view
228
        returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128)
229
    {
230
        bytes32 slot = _getPositionInfoSlot(poolId, positionId);
231

                            
                        
232
        // read all 3 words of the Position.Info struct
233
        bytes32[] memory data = manager.extsload(slot, 3);
234

                            
                        
235
        assembly ("memory-safe") {
236
            liquidity := mload(add(data, 32))
237
            feeGrowthInside0LastX128 := mload(add(data, 64))
238
            feeGrowthInside1LastX128 := mload(add(data, 96))
239
        }
240
    }
241

                            
                        
242
    function getPosition(
243
        IPoolManager manager,
244
        PoolId poolId,
245
        address owner,
246
        int24 tickLower,
247
        int24 tickUpper,
248
        bytes32 salt
249
    ) internal view returns (Position.Info memory) {
250
        // positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt))
251
        bytes32 positionKey;
252

                            
                        
253
        assembly ("memory-safe") {
254
            let fmp := mload(0x40)
255
            mstore(add(fmp, 0x26), salt) // [0x26, 0x46)
256
            mstore(add(fmp, 0x06), tickUpper) // [0x23, 0x26)
257
            mstore(add(fmp, 0x03), tickLower) // [0x20, 0x23)
258
            mstore(fmp, owner) // [0x0c, 0x20)
259
            positionKey := keccak256(add(fmp, 0x0c), 0x3a) // len is 58 bytes
260

                            
                        
261
            // now clean the memory we used
262
            mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt
263
            mstore(add(fmp, 0x20), 0) // fmp+0x20 held tickLower, tickUpper, salt
264
            mstore(fmp, 0) // fmp held owner
265
        }
266
        (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128) =
267
            getPositionInfo(manager, poolId, positionKey);
268
        return Position.Info({
269
            liquidity: liquidity,
270
            feeGrowthInside0LastX128: feeGrowthInside0LastX128,
271
            feeGrowthInside1LastX128: feeGrowthInside1LastX128
272
        });
273
    }
274

                            
                        
275
    /**
276
     * @notice Retrieves the liquidity of a position.
277
     * @dev Corresponds to pools[poolId].positions[positionId].liquidity. A more gas efficient version of getPositionInfo
278
     * @param manager The pool manager contract.
279
     * @param poolId The ID of the pool.
280
     * @param positionId The ID of the position.
281
     * @return liquidity The liquidity of the position.
282
     */
283
    function getPositionLiquidity(IPoolManager manager, PoolId poolId, bytes32 positionId)
284
        internal
285
        view
286
        returns (uint128 liquidity)
287
    {
288
        bytes32 slot = _getPositionInfoSlot(poolId, positionId);
289
        liquidity = uint128(uint256(manager.extsload(slot)));
290
    }
291

                            
                        
292
    /**
293
     * @notice Live calculate the fee growth inside a tick range of a pool
294
     * @dev pools[poolId].feeGrowthInside0LastX128 in Position.Info is cached and can become stale. This function will live calculate the feeGrowthInside
295
     * @param manager The pool manager contract.
296
     * @param poolId The ID of the pool.
297
     * @param tickLower The lower tick of the range.
298
     * @param tickUpper The upper tick of the range.
299
     * @return feeGrowthInside0X128 The fee growth inside the tick range for token0.
300
     * @return feeGrowthInside1X128 The fee growth inside the tick range for token1.
301
     */
302
    function getFeeGrowthInside(IPoolManager manager, PoolId poolId, int24 tickLower, int24 tickUpper)
303
        internal
304
        view
305
        returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128)
306
    {
307
        (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = getFeeGrowthGlobals(manager, poolId);
308

                            
                        
309
        (uint256 lowerFeeGrowthOutside0X128, uint256 lowerFeeGrowthOutside1X128) =
310
            getTickFeeGrowthOutside(manager, poolId, tickLower);
311
        (uint256 upperFeeGrowthOutside0X128, uint256 upperFeeGrowthOutside1X128) =
312
            getTickFeeGrowthOutside(manager, poolId, tickUpper);
313
        (, int24 tickCurrent,,) = getSlot0(manager, poolId);
314
        unchecked {
315
            if (tickCurrent < tickLower) {
316
                feeGrowthInside0X128 = lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128;
317
                feeGrowthInside1X128 = lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128;
318
            } else if (tickCurrent >= tickUpper) {
319
                feeGrowthInside0X128 = upperFeeGrowthOutside0X128 - lowerFeeGrowthOutside0X128;
320
                feeGrowthInside1X128 = upperFeeGrowthOutside1X128 - lowerFeeGrowthOutside1X128;
321
            } else {
322
                feeGrowthInside0X128 = feeGrowthGlobal0X128 - lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128;
323
                feeGrowthInside1X128 = feeGrowthGlobal1X128 - lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128;
324
            }
325
        }
326
    }
327

                            
                        
328
    function _getPoolStateSlot(PoolId poolId) internal pure returns (bytes32) {
329
        return keccak256(abi.encodePacked(PoolId.unwrap(poolId), POOLS_SLOT));
330
    }
331

                            
                        
332
    function _getTickInfoSlot(PoolId poolId, int24 tick) internal pure returns (bytes32) {
333
        // slot key of Pool.State value: `pools[poolId]`
334
        bytes32 stateSlot = _getPoolStateSlot(poolId);
335

                            
                        
336
        // Pool.State: `mapping(int24 => TickInfo) ticks`
337
        bytes32 ticksMappingSlot = bytes32(uint256(stateSlot) + TICKS_OFFSET);
338

                            
                        
339
        // slot key of the tick key: `pools[poolId].ticks[tick]
340
        return keccak256(abi.encodePacked(int256(tick), ticksMappingSlot));
341
    }
342

                            
                        
343
    function _getPositionInfoSlot(PoolId poolId, bytes32 positionId) internal pure returns (bytes32) {
344
        // slot key of Pool.State value: `pools[poolId]`
345
        bytes32 stateSlot = _getPoolStateSlot(poolId);
346

                            
                        
347
        // Pool.State: `mapping(bytes32 => Position.Info) positions;`
348
        bytes32 positionMapping = bytes32(uint256(stateSlot) + POSITIONS_OFFSET);
349

                            
                        
350
        // slot of the mapping key: `pools[poolId].positions[positionId]
351
        return keccak256(abi.encodePacked(positionId, positionMapping));
352
    }
353
}
354

                            
                        

Lines covered: 39 / 41 (95.1%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {FullMath} from "./FullMath.sol";
5
import {SqrtPriceMath} from "./SqrtPriceMath.sol";
6

                            
                        
7
/// @title Computes the result of a swap within ticks
8
/// @notice Contains methods for computing the result of a swap within a single tick price range, i.e., a single tick.
9
library SwapMath {
10
√ 5045
⟳ 10409
    uint256 internal constant MAX_FEE_PIPS = 1e6;
11

                            
                        
12
    /// @notice Computes the sqrt price target for the next swap step
13
    /// @param zeroForOne The direction of the swap, true for currency0 to currency1, false for currency1 to currency0
14
    /// @param sqrtPriceNextX96 The Q64.96 sqrt price for the next initialized tick
15
    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this value
16
    /// after the swap. If one for zero, the price cannot be greater than this value after the swap
17
    /// @return sqrtPriceTargetX96 The price target for the next swap step
18
    function getSqrtPriceTarget(bool zeroForOne, uint160 sqrtPriceNextX96, uint160 sqrtPriceLimitX96)
19
        internal
20
        pure
21
        returns (uint160 sqrtPriceTargetX96)
22
    {
23
        assembly ("memory-safe") {
24
            // a flag to toggle between sqrtPriceNextX96 and sqrtPriceLimitX96
25
            // when zeroForOne == true, nextOrLimit reduces to sqrtPriceNextX96 >= sqrtPriceLimitX96
26
            // sqrtPriceTargetX96 = max(sqrtPriceNextX96, sqrtPriceLimitX96)
27
            // when zeroForOne == false, nextOrLimit reduces to sqrtPriceNextX96 < sqrtPriceLimitX96
28
            // sqrtPriceTargetX96 = min(sqrtPriceNextX96, sqrtPriceLimitX96)
29
            sqrtPriceNextX96 := and(sqrtPriceNextX96, 0xffffffffffffffffffffffffffffffffffffffff)
30
√ 790
⟳ 6
            sqrtPriceLimitX96 := and(sqrtPriceLimitX96, 0xffffffffffffffffffffffffffffffffffffffff)
31
√ 395
⟳ 3
            let nextOrLimit := xor(lt(sqrtPriceNextX96, sqrtPriceLimitX96), and(zeroForOne, 0xff))
32
√ 1185
⟳ 9
            let symDiff := xor(sqrtPriceNextX96, sqrtPriceLimitX96)
33
√ 1580
⟳ 12
            sqrtPriceTargetX96 := xor(sqrtPriceLimitX96, mul(symDiff, nextOrLimit))
34
        }
35
    }
36

                            
                        
37
    /// @notice Computes the result of swapping some amount in, or amount out, given the parameters of the swap
38
    /// @dev If the swap's amountSpecified is negative, the combined fee and input amount will never exceed the absolute value of the remaining amount.
39
    /// @param sqrtPriceCurrentX96 The current sqrt price of the pool
40
    /// @param sqrtPriceTargetX96 The price that cannot be exceeded, from which the direction of the swap is inferred
41
    /// @param liquidity The usable liquidity
42
    /// @param amountRemaining How much input or output amount is remaining to be swapped in/out
43
    /// @param feePips The fee taken from the input amount, expressed in hundredths of a bip
44
    /// @return sqrtPriceNextX96 The price after swapping the amount in/out, not to exceed the price target
45
    /// @return amountIn The amount to be swapped in, of either currency0 or currency1, based on the direction of the swap
46
    /// @return amountOut The amount to be received, of either currency0 or currency1, based on the direction of the swap
47
    /// @return feeAmount The amount of input that will be taken as a fee/
48
    /// @dev feePips must be no larger than MAX_FEE_PIPS for this function. We ensure that before setting a fee using LPFeeLibrary.isValid.
49
    function computeSwapStep(
50
        uint160 sqrtPriceCurrentX96,
51
        uint160 sqrtPriceTargetX96,
52
        uint128 liquidity,
53
        int256 amountRemaining,
54
        uint24 feePips
55
√ 1580
⟳ 12
    ) internal pure returns (uint160 sqrtPriceNextX96, uint256 amountIn, uint256 amountOut, uint256 feeAmount) {
56
        unchecked {
57
√ 1185
⟳ 9
            uint256 _feePips = feePips; // upcast once and cache
58
√ 3555
⟳ 27
            bool zeroForOne = sqrtPriceCurrentX96 >= sqrtPriceTargetX96;
59
√ 1185
⟳ 9
            bool exactIn = amountRemaining < 0;
60

                            
                        
61
            if (exactIn) {
62
√ 395
⟳ 3
                uint256 amountRemainingLessFee =
63
√ 1185
⟳ 9
                    FullMath.mulDiv(uint256(-amountRemaining), MAX_FEE_PIPS - _feePips, MAX_FEE_PIPS);
64
√ 395
⟳ 3
                amountIn = zeroForOne
65
√ 17335
⟳ 15
                    ? SqrtPriceMath.getAmount0Delta(sqrtPriceTargetX96, sqrtPriceCurrentX96, liquidity, true)
66
√ 1975
⟳ 34670
                    : SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceTargetX96, liquidity, true);
67
√ 790
⟳ 6
                if (amountRemainingLessFee >= amountIn) {
68
                    // `amountIn` is capped by the target price
69
√ 394
⟳ 2
                    sqrtPriceNextX96 = sqrtPriceTargetX96;
70
√ 394
⟳ 2
                    feeAmount = _feePips == MAX_FEE_PIPS
71
√ 3467
⟳ 2
                        ? amountIn
72
√ 1576
⟳ 13868
                        : FullMath.mulDivRoundingUp(amountIn, _feePips, MAX_FEE_PIPS - _feePips);
73
                } else {
74
√ 1
⟳ 1
                    sqrtPriceNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput(
75
√ 4
⟳ 4
                        sqrtPriceCurrentX96, liquidity, amountRemainingLessFee, zeroForOne
76
                    );
77
√ 1
⟳ 1
                    amountIn = zeroForOne
78
√ 5
⟳ 5
                        ? SqrtPriceMath.getAmount0Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, true)
79
√ 5
⟳ 5
                        : SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, true);
80
                    // we didn't reach the target, so take the remainder of the maximum input as fee
81
√ 2
⟳ 2
                    feeAmount = uint256(-amountRemaining) - amountIn;
82
                }
83
√ 395
⟳ 3
                amountOut = zeroForOne
84
√ 17335
⟳ 15
                    ? SqrtPriceMath.getAmount1Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, false)
85
√ 1975
⟳ 34670
                    : SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, false);
86
            } else {
87
√ 3467
⟳ 6934
                amountOut = zeroForOne
88
√ 17335
⟳ 5
                    ? SqrtPriceMath.getAmount1Delta(sqrtPriceTargetX96, sqrtPriceCurrentX96, liquidity, false)
89
√ 17335
⟳ 34670
                    : SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceTargetX96, liquidity, false);
90
√ 6934
⟳ 13868
                if (uint256(amountRemaining) >= amountOut) {
91
                    // `amountOut` is capped by the target price
92
√ 3467
⟳ 6934
                    sqrtPriceNextX96 = sqrtPriceTargetX96;
93
                } else {
94
                    // cap the output amount to not exceed the remaining output amount
95
√ 1
⟳ 1
                    amountOut = uint256(amountRemaining);
96
                    sqrtPriceNextX96 =
97
√ 5
⟳ 5
                        SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtPriceCurrentX96, liquidity, amountOut, zeroForOne);
98
                }
99
√ 3467
⟳ 6934
                amountIn = zeroForOne
100
√ 17335
⟳ 5
                    ? SqrtPriceMath.getAmount0Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, true)
101
√ 17335
⟳ 34670
                    : SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, true);
102
                // `feePips` cannot be `MAX_FEE_PIPS` for exact out
103
√ 13868
⟳ 27736
                feeAmount = FullMath.mulDivRoundingUp(amountIn, _feePips, MAX_FEE_PIPS - _feePips);
104
            }
105
        }
106
    }
107
}
108

                            
                        

Lines covered: 32 / 34 (94.1%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {BitMath} from "./BitMath.sol";
5

                            
                        
6
/// @title Packed tick initialized state library
7
/// @notice Stores a packed mapping of tick index to its initialized state
8
/// @dev The mapping uses int16 for keys since ticks are represented as int24 and there are 256 (2^8) values per word.
9
library TickBitmap {
10
    /// @notice Thrown when the tick is not enumerated by the tick spacing
11
    /// @param tick the invalid tick
12
    /// @param tickSpacing The tick spacing of the pool
13
    error TickMisaligned(int24 tick, int24 tickSpacing);
14

                            
                        
15
    /// @dev round towards negative infinity
16
    function compress(int24 tick, int24 tickSpacing) internal pure returns (int24 compressed) {
17
        // compressed = tick / tickSpacing;
18
        // if (tick < 0 && tick % tickSpacing != 0) compressed--;
19
        assembly ("memory-safe") {
20
√ 395
⟳ 3
            tick := signextend(2, tick)
21
√ 1185
⟳ 9
            tickSpacing := signextend(2, tickSpacing)
22
            compressed :=
23
                sub(
24
√ 1185
⟳ 9
                    sdiv(tick, tickSpacing),
25
                    // if (tick < 0 && tick % tickSpacing != 0) then tick % tickSpacing < 0, vice versa
26
√ 1185
⟳ 9
                    slt(smod(tick, tickSpacing), 0)
27
                )
28
        }
29
    }
30

                            
                        
31
    /// @notice Computes the position in the mapping where the initialized bit for a tick lives
32
    /// @param tick The tick for which to compute the position
33
    /// @return wordPos The key in the mapping containing the word in which the bit is stored
34
    /// @return bitPos The bit position in the word where the flag is stored
35
    function position(int24 tick) internal pure returns (int16 wordPos, uint8 bitPos) {
36
        assembly ("memory-safe") {
37
            // signed arithmetic shift right
38
√ 7724
⟳ 13874
            wordPos := sar(8, signextend(2, tick))
39
√ 3862
⟳ 6937
            bitPos := and(tick, 0xff)
40
        }
41
    }
42

                            
                        
43
    /// @notice Flips the initialized state for a given tick from false to true, or vice versa
44
    /// @param self The mapping in which to flip the tick
45
    /// @param tick The tick to flip
46
    /// @param tickSpacing The spacing between usable ticks
47
    function flipTick(mapping(int16 => uint256) storage self, int24 tick, int24 tickSpacing) internal {
48
        // Equivalent to the following Solidity:
49
        //     if (tick % tickSpacing != 0) revert TickMisaligned(tick, tickSpacing);
50
        //     (int16 wordPos, uint8 bitPos) = position(tick / tickSpacing);
51
        //     uint256 mask = 1 << bitPos;
52
        //     self[wordPos] ^= mask;
53
        assembly ("memory-safe") {
54
√ 2
⟳ 2
            tick := signextend(2, tick)
55
√ 2
⟳ 2
            tickSpacing := signextend(2, tickSpacing)
56
            // ensure that the tick is spaced
57
√ 6
⟳ 6
            if smod(tick, tickSpacing) {
58
⟳ 1
                let fmp := mload(0x40)
59
⟳ 2
                mstore(fmp, 0xd4d8f3e6) // selector for TickMisaligned(int24,int24)
60
⟳ 3
                mstore(add(fmp, 0x20), tick)
61
⟳ 3
                mstore(add(fmp, 0x40), tickSpacing)
62
⟳ 3
                revert(add(fmp, 0x1c), 0x44)
63
            }
64
√ 4
⟳ 4
            tick := sdiv(tick, tickSpacing)
65
            // calculate the storage slot corresponding to the tick
66
            // wordPos = tick >> 8
67
√ 6
⟳ 6
            mstore(0, sar(8, tick))
68
√ 4
⟳ 4
            mstore(0x20, self.slot)
69
            // the slot of self[wordPos] is keccak256(abi.encode(wordPos, self.slot))
70
√ 4
⟳ 4
            let slot := keccak256(0, 0x40)
71
            // mask = 1 << bitPos = 1 << (tick % 256)
72
            // self[wordPos] ^= mask
73
√ 10
⟳ 10
            sstore(slot, xor(sload(slot), shl(and(tick, 0xff), 1)))
74
        }
75
    }
76

                            
                        
77
    /// @notice Returns the next initialized tick contained in the same word (or adjacent word) as the tick that is either
78
    /// to the left (less than or equal to) or right (greater than) of the given tick
79
    /// @param self The mapping in which to compute the next initialized tick
80
    /// @param tick The starting tick
81
    /// @param tickSpacing The spacing between usable ticks
82
    /// @param lte Whether to search for the next initialized tick to the left (less than or equal to the starting tick)
83
    /// @return next The next initialized or uninitialized tick up to 256 ticks away from the current tick
84
    /// @return initialized Whether the next tick is initialized, as the function only searches within up to 256 ticks
85
    function nextInitializedTickWithinOneWord(
86
        mapping(int16 => uint256) storage self,
87
        int24 tick,
88
        int24 tickSpacing,
89
        bool lte
90
√ 790
⟳ 6
    ) internal view returns (int24 next, bool initialized) {
91
        unchecked {
92
            int24 compressed = compress(tick, tickSpacing);
93

                            
                        
94
            if (lte) {
95
√ 3467
⟳ 3
                (int16 wordPos, uint8 bitPos) = position(compressed);
96
                // all the 1s at or to the right of the current bitPos
97
√ 13868
⟳ 12
                uint256 mask = (1 << (uint256(bitPos) + 1)) - 1;
98
√ 48538
⟳ 42
                uint256 masked = self[wordPos] & mask;
99

                            
                        
100
                // if there are no initialized ticks to the right of or at the current tick, return rightmost in the word
101
√ 17335
⟳ 15
                initialized = masked != 0;
102
                // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick
103
                next = initialized
104
√ 5
⟳ 10
                    ? (compressed - int24(uint24(bitPos - BitMath.mostSignificantBit(masked)))) * tickSpacing
105
√ 10398
⟳ 3
                    : (compressed - int24(uint24(bitPos))) * tickSpacing;
106
            } else {
107
                // start from the word of the next tick, since the current tick state doesn't matter
108
√ 2765
⟳ 48538
                (int16 wordPos, uint8 bitPos) = position(++compressed);
109
                // all the 1s at or to the left of the bitPos
110
√ 1185
⟳ 20802
                uint256 mask = ~((1 << bitPos) - 1);
111
√ 5530
⟳ 97076
                uint256 masked = self[wordPos] & mask;
112

                            
                        
113
                // if there are no initialized ticks to the left of the current tick, return leftmost in the word
114
√ 1975
⟳ 34670
                initialized = masked != 0;
115
                // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick
116
                next = initialized
117
√ 5
⟳ 10
                    ? (compressed + int24(uint24(BitMath.leastSignificantBit(masked) - bitPos))) * tickSpacing
118
√ 1576
⟳ 27728
                    : (compressed + int24(uint24(type(uint8).max - bitPos))) * tickSpacing;
119
            }
120
        }
121
    }
122
}
123

                            
                        

Lines covered: 121 / 126 (96.0%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {CustomRevert} from "./CustomRevert.sol";
5

                            
                        
6
/// @title Math library for computing sqrt prices from ticks and vice versa
7
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
8
/// prices between 2**-128 and 2**128
9
library TickMath {
10
    using CustomRevert for bytes4;
11

                            
                        
12
    /// @notice Thrown when the tick passed to #getSqrtPriceAtTick is not between MIN_TICK and MAX_TICK
13
    error InvalidTick(int24 tick);
14
    /// @notice Thrown when the price passed to #getTickAtSqrtPrice does not correspond to a price between MIN_TICK and MAX_TICK
15
    error InvalidSqrtPrice(uint160 sqrtPriceX96);
16

                            
                        
17
    /// @dev The minimum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**-128
18
√ 398
⟳ 6
    int24 internal constant MIN_TICK = -887272;
19
    /// @dev The maximum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**128
20
√ 399
⟳ 7
    int24 internal constant MAX_TICK = 887272;
21

                            
                        
22
    /// @dev The minimum tick spacing value drawn from the range of type int16 that is greater than 0, i.e. min from the range [1, 32767]
23
√ 1
⟳ 1
    int24 internal constant MIN_TICK_SPACING = 1;
24
    /// @dev The maximum tick spacing value drawn from the range of type int16, i.e. max from the range [1, 32767]
25
√ 1
⟳ 1
    int24 internal constant MAX_TICK_SPACING = type(int16).max;
26

                            
                        
27
    /// @dev The minimum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MIN_TICK)
28
√ 1
⟳ 1
    uint160 internal constant MIN_SQRT_PRICE = 4295128739;
29
    /// @dev The maximum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MAX_TICK)
30
√ 1
⟳ 1
    uint160 internal constant MAX_SQRT_PRICE = 1461446703485210103287273052203988822378723970342;
31
    /// @dev A threshold used for optimized bounds check, equals `MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1`
32
    uint160 internal constant MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE =
33
√ 1
⟳ 1
        1461446703485210103287273052203988822378723970342 - 4295128739 - 1;
34

                            
                        
35
    /// @notice Given a tickSpacing, compute the maximum usable tick
36
    function maxUsableTick(int24 tickSpacing) internal pure returns (int24) {
37
        unchecked {
38
            return (MAX_TICK / tickSpacing) * tickSpacing;
39
        }
40
    }
41

                            
                        
42
    /// @notice Given a tickSpacing, compute the minimum usable tick
43
    function minUsableTick(int24 tickSpacing) internal pure returns (int24) {
44
        unchecked {
45
            return (MIN_TICK / tickSpacing) * tickSpacing;
46
        }
47
    }
48

                            
                        
49
    /// @notice Calculates sqrt(1.0001^tick) * 2^96
50
    /// @dev Throws if |tick| > max tick
51
    /// @param tick The input tick for the above formula
52
    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the price of the two assets (currency1/currency0)
53
    /// at the given tick
54
√ 1
⟳ 1
    function getSqrtPriceAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
55
        unchecked {
56
            uint256 absTick;
57
            assembly ("memory-safe") {
58
√ 1
⟳ 1
                tick := signextend(2, tick)
59
                // mask = 0 if tick >= 0 else -1 (all 1s)
60
√ 1
⟳ 1
                let mask := sar(255, tick)
61
                // if tick >= 0, |tick| = tick = 0 ^ tick
62
                // if tick < 0, |tick| = ~~|tick| = ~(-|tick| - 1) = ~(tick - 1) = (-1) ^ (tick - 1)
63
                // either way, |tick| = mask ^ (tick + mask)
64
√ 3
⟳ 3
                absTick := xor(mask, add(mask, tick))
65
            }
66

                            
                        
67
√ 2
⟳ 2
            if (absTick > uint256(int256(MAX_TICK))) InvalidTick.selector.revertWith(tick);
68

                            
                        
69
            // Equivalent to:
70
            //     price = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;
71
            //     or price = int(2**128 / sqrt(1.0001)) if (absTick & 0x1) else 1 << 128
72
            uint256 price;
73
            assembly ("memory-safe") {
74
√ 2
⟳ 2
                price := xor(shl(128, 1), mul(xor(shl(128, 1), 0xfffcb933bd6fad37aa2d162d1a594001), and(absTick, 0x1)))
75
            }
76
√ 3
⟳ 3
            if (absTick & 0x2 != 0) price = (price * 0xfff97272373d413259a46990580e213a) >> 128;
77
√ 3
⟳ 3
            if (absTick & 0x4 != 0) price = (price * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
78
√ 3
⟳ 3
            if (absTick & 0x8 != 0) price = (price * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
79
√ 3
⟳ 3
            if (absTick & 0x10 != 0) price = (price * 0xffcb9843d60f6159c9db58835c926644) >> 128;
80
√ 791
⟳ 3
            if (absTick & 0x20 != 0) price = (price * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
81
√ 3
⟳ 3
            if (absTick & 0x40 != 0) price = (price * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
82
√ 3
⟳ 3
            if (absTick & 0x80 != 0) price = (price * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
83
√ 397
⟳ 3
            if (absTick & 0x100 != 0) price = (price * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
84
√ 393
⟳ 3
            if (absTick & 0x200 != 0) price = (price * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
85
√ 393
⟳ 3
            if (absTick & 0x400 != 0) price = (price * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
86
√ 3
⟳ 3
            if (absTick & 0x800 != 0) price = (price * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
87
√ 385
⟳ 3
            if (absTick & 0x1000 != 0) price = (price * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
88
√ 385
⟳ 3
            if (absTick & 0x2000 != 0) price = (price * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
89
√ 385
⟳ 3
            if (absTick & 0x4000 != 0) price = (price * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
90
√ 3
⟳ 3
            if (absTick & 0x8000 != 0) price = (price * 0x31be135f97d08fd981231505542fcfa6) >> 128;
91
√ 3
⟳ 3
            if (absTick & 0x10000 != 0) price = (price * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
92
√ 3
⟳ 3
            if (absTick & 0x20000 != 0) price = (price * 0x5d6af8dedb81196699c329225ee604) >> 128;
93
√ 2841
⟳ 3
            if (absTick & 0x40000 != 0) price = (price * 0x2216e584f5fa1ea926041bedfe98) >> 128;
94
√ 3
⟳ 3
            if (absTick & 0x80000 != 0) price = (price * 0x48a170391f7dc42444e8fa2) >> 128;
95

                            
                        
96
            assembly ("memory-safe") {
97
                // if (tick > 0) price = type(uint256).max / price;
98
√ 3
⟳ 3
                if sgt(tick, 0) { price := div(not(0), price) }
99

                            
                        
100
                // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
101
                // we then downcast because we know the result always fits within 160 bits due to our tick input constraint
102
                // we round up in the division so getTickAtSqrtPrice of the output price is always consistent
103
                // `sub(shl(32, 1), 1)` is `type(uint32).max`
104
                // `price + type(uint32).max` will not overflow because `price` fits in 192 bits
105
√ 1
⟳ 1
                sqrtPriceX96 := shr(32, add(price, sub(shl(32, 1), 1)))
106
            }
107
        }
108
    }
109

                            
                        
110
    /// @notice Calculates the greatest tick value such that getPriceAtTick(tick) <= price
111
    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_PRICE, as MIN_SQRT_PRICE is the lowest value getPriceAtTick may
112
    /// ever return.
113
    /// @param sqrtPriceX96 The sqrt price for which to compute the tick as a Q64.96
114
    /// @return tick The greatest tick for which the price is less than or equal to the input price
115
√ 1
⟳ 1
    function getTickAtSqrtPrice(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
116
        unchecked {
117
            // Equivalent: if (sqrtPriceX96 < MIN_SQRT_PRICE || sqrtPriceX96 >= MAX_SQRT_PRICE) revert InvalidSqrtPrice();
118
            // second inequality must be >= because the price can never reach the price at the max tick
119
            // if sqrtPriceX96 < MIN_SQRT_PRICE, the `sub` underflows and `gt` is true
120
            // if sqrtPriceX96 >= MAX_SQRT_PRICE, sqrtPriceX96 - MIN_SQRT_PRICE > MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1
121
√ 3
⟳ 3
            if ((sqrtPriceX96 - MIN_SQRT_PRICE) > MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE) {
122
⟳ 2
                InvalidSqrtPrice.selector.revertWith(sqrtPriceX96);
123
            }
124

                            
                        
125
√ 1
⟳ 1
            uint256 price = uint256(sqrtPriceX96) << 32;
126

                            
                        
127
            uint256 r = price;
128
            uint256 msb = 0;
129

                            
                        
130
            assembly ("memory-safe") {
131
√ 2
⟳ 2
                let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
132
                msb := or(msb, f)
133
√ 3
⟳ 3
                r := shr(f, r)
134
            }
135
            assembly ("memory-safe") {
136
√ 2
⟳ 2
                let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
137
√ 2
⟳ 2
                msb := or(msb, f)
138
√ 3
⟳ 3
                r := shr(f, r)
139
            }
140
            assembly ("memory-safe") {
141
√ 2
⟳ 2
                let f := shl(5, gt(r, 0xFFFFFFFF))
142
√ 3
⟳ 3
                msb := or(msb, f)
143
√ 3
⟳ 3
                r := shr(f, r)
144
            }
145
            assembly ("memory-safe") {
146
√ 2
⟳ 2
                let f := shl(4, gt(r, 0xFFFF))
147
√ 3
⟳ 3
                msb := or(msb, f)
148
√ 3
⟳ 3
                r := shr(f, r)
149
            }
150
            assembly ("memory-safe") {
151
√ 2
⟳ 2
                let f := shl(3, gt(r, 0xFF))
152
√ 1
⟳ 1
                msb := or(msb, f)
153
√ 3
⟳ 3
                r := shr(f, r)
154
            }
155
            assembly ("memory-safe") {
156
√ 2
⟳ 2
                let f := shl(2, gt(r, 0xF))
157
√ 3
⟳ 3
                msb := or(msb, f)
158
√ 3
⟳ 3
                r := shr(f, r)
159
            }
160
            assembly ("memory-safe") {
161
√ 4
⟳ 4
                let f := shl(1, gt(r, 0x3))
162
√ 1
⟳ 1
                msb := or(msb, f)
163
√ 4
⟳ 4
                r := shr(f, r)
164
            }
165
            assembly ("memory-safe") {
166
√ 3
⟳ 3
                let f := gt(r, 0x1)
167
√ 1
⟳ 1
                msb := or(msb, f)
168
            }
169

                            
                        
170
√ 4
⟳ 4
            if (msb >= 128) r = price >> (msb - 127);
171
√ 3
⟳ 3
            else r = price << (127 - msb);
172

                            
                        
173
√ 2
⟳ 2
            int256 log_2 = (int256(msb) - 128) << 64;
174

                            
                        
175
            assembly ("memory-safe") {
176
√ 5
⟳ 5
                r := shr(127, mul(r, r))
177
√ 4
⟳ 4
                let f := shr(128, r)
178
√ 7
⟳ 7
                log_2 := or(log_2, shl(63, f))
179
√ 4
⟳ 4
                r := shr(f, r)
180
            }
181
            assembly ("memory-safe") {
182
√ 2
⟳ 2
                r := shr(127, mul(r, r))
183
√ 3
⟳ 3
                let f := shr(128, r)
184
√ 7
⟳ 7
                log_2 := or(log_2, shl(62, f))
185
√ 1
⟳ 1
                r := shr(f, r)
186
            }
187
            assembly ("memory-safe") {
188
√ 2
⟳ 2
                r := shr(127, mul(r, r))
189
√ 3
⟳ 3
                let f := shr(128, r)
190
√ 7
⟳ 7
                log_2 := or(log_2, shl(61, f))
191
√ 1
⟳ 1
                r := shr(f, r)
192
            }
193
            assembly ("memory-safe") {
194
√ 2
⟳ 2
                r := shr(127, mul(r, r))
195
√ 3
⟳ 3
                let f := shr(128, r)
196
√ 7
⟳ 7
                log_2 := or(log_2, shl(60, f))
197
√ 1
⟳ 1
                r := shr(f, r)
198
            }
199
            assembly ("memory-safe") {
200
√ 2
⟳ 2
                r := shr(127, mul(r, r))
201
√ 3
⟳ 3
                let f := shr(128, r)
202
√ 7
⟳ 7
                log_2 := or(log_2, shl(59, f))
203
√ 1
⟳ 1
                r := shr(f, r)
204
            }
205
            assembly ("memory-safe") {
206
√ 2
⟳ 2
                r := shr(127, mul(r, r))
207
√ 3
⟳ 3
                let f := shr(128, r)
208
√ 7
⟳ 7
                log_2 := or(log_2, shl(58, f))
209
√ 1
⟳ 1
                r := shr(f, r)
210
            }
211
            assembly ("memory-safe") {
212
√ 2
⟳ 2
                r := shr(127, mul(r, r))
213
√ 3
⟳ 3
                let f := shr(128, r)
214
√ 7
⟳ 7
                log_2 := or(log_2, shl(57, f))
215
√ 1
⟳ 1
                r := shr(f, r)
216
            }
217
            assembly ("memory-safe") {
218
√ 2
⟳ 2
                r := shr(127, mul(r, r))
219
√ 3
⟳ 3
                let f := shr(128, r)
220
√ 7
⟳ 7
                log_2 := or(log_2, shl(56, f))
221
√ 1
⟳ 1
                r := shr(f, r)
222
            }
223
            assembly ("memory-safe") {
224
√ 2
⟳ 2
                r := shr(127, mul(r, r))
225
√ 3
⟳ 3
                let f := shr(128, r)
226
√ 7
⟳ 7
                log_2 := or(log_2, shl(55, f))
227
√ 1
⟳ 1
                r := shr(f, r)
228
            }
229
            assembly ("memory-safe") {
230
√ 2
⟳ 2
                r := shr(127, mul(r, r))
231
√ 3
⟳ 3
                let f := shr(128, r)
232
√ 7
⟳ 7
                log_2 := or(log_2, shl(54, f))
233
√ 1
⟳ 1
                r := shr(f, r)
234
            }
235
            assembly ("memory-safe") {
236
√ 2
⟳ 2
                r := shr(127, mul(r, r))
237
√ 3
⟳ 3
                let f := shr(128, r)
238
√ 7
⟳ 7
                log_2 := or(log_2, shl(53, f))
239
√ 1
⟳ 1
                r := shr(f, r)
240
            }
241
            assembly ("memory-safe") {
242
√ 2
⟳ 2
                r := shr(127, mul(r, r))
243
√ 3
⟳ 3
                let f := shr(128, r)
244
√ 7
⟳ 7
                log_2 := or(log_2, shl(52, f))
245
√ 1
⟳ 1
                r := shr(f, r)
246
            }
247
            assembly ("memory-safe") {
248
√ 2
⟳ 2
                r := shr(127, mul(r, r))
249
√ 4
⟳ 4
                let f := shr(128, r)
250
√ 7
⟳ 7
                log_2 := or(log_2, shl(51, f))
251
√ 4
⟳ 4
                r := shr(f, r)
252
            }
253
            assembly ("memory-safe") {
254
√ 2
⟳ 2
                r := shr(127, mul(r, r))
255
                let f := shr(128, r)
256
√ 7
⟳ 7
                log_2 := or(log_2, shl(50, f))
257
            }
258

                            
                        
259
√ 1
⟳ 1
            int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number
260

                            
                        
261
√ 3
⟳ 3
            int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
262
√ 1
⟳ 1
            int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);
263

                            
                        
264
√ 15
⟳ 15
            tick = tickLow == tickHi ? tickLow : getSqrtPriceAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
265
        }
266
    }
267
}
268

                            
                        

Lines covered: 0 / 16 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {IPoolManager} from "../interfaces/IPoolManager.sol";
5
import {Currency} from "../types/Currency.sol";
6
import {CurrencyReserves} from "./CurrencyReserves.sol";
7
import {NonZeroDeltaCount} from "./NonZeroDeltaCount.sol";
8
import {Lock} from "./Lock.sol";
9

                            
                        
10
/// @notice A helper library to provide state getters that use exttload
11
library TransientStateLibrary {
12
    /// @notice returns the reserves for the synced currency
13
    /// @param manager The pool manager contract.
14

                            
                        
15
    /// @return uint256 The reserves of the currency.
16
    /// @dev returns 0 if the reserves are not synced or value is 0.
17
    /// Checks the synced currency to only return valid reserve values (after a sync and before a settle).
18
    function getSyncedReserves(IPoolManager manager) internal view returns (uint256) {
19
        if (getSyncedCurrency(manager).isZero()) return 0;
20
        return uint256(manager.exttload(CurrencyReserves.RESERVES_OF_SLOT));
21
    }
22

                            
                        
23
    function getSyncedCurrency(IPoolManager manager) internal view returns (Currency) {
24
        return Currency.wrap(address(uint160(uint256(manager.exttload(CurrencyReserves.CURRENCY_SLOT)))));
25
    }
26

                            
                        
27
    /// @notice Returns the number of nonzero deltas open on the PoolManager that must be zerod out before the contract is locked
28
    function getNonzeroDeltaCount(IPoolManager manager) internal view returns (uint256) {
29
        return uint256(manager.exttload(NonZeroDeltaCount.NONZERO_DELTA_COUNT_SLOT));
30
    }
31

                            
                        
32
    /// @notice Get the current delta for a caller in the given currency
33
    /// @param target The credited account address
34
    /// @param currency The currency for which to lookup the delta
35
    function currencyDelta(IPoolManager manager, address target, Currency currency) internal view returns (int256) {
36
        bytes32 key;
37
        assembly ("memory-safe") {
38
            mstore(0, and(target, 0xffffffffffffffffffffffffffffffffffffffff))
39
            mstore(32, and(currency, 0xffffffffffffffffffffffffffffffffffffffff))
40
            key := keccak256(0, 64)
41
        }
42
        return int256(uint256(manager.exttload(key)));
43
    }
44

                            
                        
45
    /// @notice Returns whether the contract is unlocked or not
46
    function isUnlocked(IPoolManager manager) internal view returns (bool) {
47
        return manager.exttload(Lock.IS_UNLOCKED_SLOT) != 0x0;
48
    }
49
}
50

                            
                        

Lines covered: 1 / 2 (50.0%)

1
// SPDX-License-Identifier: GPL-2.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
/// @title Math functions that do not check inputs or outputs
5
/// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks
6
library UnsafeMath {
7
    /// @notice Returns ceil(x / y)
8
    /// @dev division by 0 has unspecified behavior, and must be checked externally
9
    /// @param x The dividend
10
    /// @param y The divisor
11
    /// @return z The quotient, ceil(x / y)
12
    function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
13
        unchecked {
14
            assembly ("memory-safe") {
15
√ 10
⟳ 10
                z := add(div(x, y), gt(mod(x, y), 0))
16
            }
17
        }
18
    }
19
}
20

                            
                        

Lines covered: 85 / 148 (57.4%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import "forge-std/Test.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
7
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
8

                            
                        
9
import {Currency} from "../types/Currency.sol";
10
import {PoolKey} from "../types/PoolKey.sol";
11
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
12
import {StateLibrary} from "../libraries/StateLibrary.sol";
13
import {TransientStateLibrary} from "../libraries/TransientStateLibrary.sol";
14
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
15
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
16
import {IHooks} from "src/interfaces/IHooks.sol";
17
import {PoolKey} from "src/types/PoolKey.sol";
18
import {IActionsHarness} from "../../test/trailofbits/IActionsHarness.sol";
19

                            
                        
20
// Supported Actions.
21
enum Actions {
22
    SETTLE,
23
    SETTLE_NATIVE,
24
    SETTLE_FOR,
25
    TAKE,
26
    PRANK_TAKE_FROM,
27
    SYNC,
28
    MINT,
29
    BURN,
30
    CLEAR,
31
    ASSERT_BALANCE_EQUALS,
32
    ASSERT_RESERVES_EQUALS,
33
    ASSERT_DELTA_EQUALS,
34
    ASSERT_NONZERO_DELTA_COUNT_EQUALS,
35
    TRANSFER_FROM,
36
    INITIALIZE,
37
    DONATE,
38
    MODIFY_POSITION,
39
    SWAP,
40
    HARNESS_CALLBACK
41
}
42

                            
                        
43
/// @notice A router that handles an arbitrary input of actions.
44
/// TODO: Can continue to add functions per action.
45
contract ActionsRouter is IUnlockCallback, Test {
46
    using StateLibrary for IPoolManager;
47
    using TransientStateLibrary for IPoolManager;
48
    using PoolIdLibrary for PoolKey;
49

                            
                        
50
    error ActionNotSupported();
51

                            
                        
52
    // error thrown so that incorrectly formatted tests don't pass silently
53
    error CheckParameters();
54

                            
                        
55
    error AssertOnExceptionNotSupported();
56

                            
                        
57
    IPoolManager manager;
58
    bytes lastReturnData;
59
√ 8
    bool assertOnException = false;
60

                            
                        
61
    constructor(IPoolManager _manager) {
62
√ 1
        manager = _manager;
63
    }
64

                            
                        
65
√ 1
⟳ 1
    function unlockCallback(bytes calldata data) external returns (bytes memory) {
66
√ 3
⟳ 3
        (Actions[] memory actions, bytes[] memory params) = abi.decode(data, (Actions[], bytes[]));
67
√ 4
⟳ 18
        if (actions.length != params.length || actions.length == 0) revert CheckParameters();
68
√ 42
⟳ 12
        for (uint256 i = 0; i < actions.length; i++) {
69
√ 39
⟳ 12
            Actions action = actions[i];
70
√ 39
⟳ 12
            bytes memory param = params[i];
71
√ 26
⟳ 8
            if (action == Actions.SETTLE) {
72
√ 1
⟳ 1
                _settle();
73
√ 24
⟳ 8
            } else if (action == Actions.SETTLE_NATIVE) {
74
√ 2
⟳ 2
                _settleNative(param);
75
√ 24
⟳ 8
            } else if (action == Actions.SETTLE_FOR) {
76
√ 2
⟳ 2
                _settleFor(param);
77
√ 24
⟳ 8
            } else if (action == Actions.TAKE) {
78
√ 2
⟳ 2
                _take(param);
79
√ 22
⟳ 8
            } else if (action == Actions.PRANK_TAKE_FROM) {
80
                _prankTakeFrom(param);
81
√ 22
⟳ 8
            } else if (action == Actions.SYNC) {
82
√ 2
⟳ 2
                _sync(param);
83
√ 20
⟳ 8
            } else if (action == Actions.MODIFY_POSITION) {
84
√ 2
⟳ 2
                _modify_position(param);
85
√ 18
⟳ 8
            } else if (action == Actions.MINT) {
86
√ 2
⟳ 2
                _mint(param);
87
√ 18
⟳ 8
            } else if (action == Actions.BURN) {
88
√ 2
⟳ 2
                _burn(param);
89
√ 18
⟳ 8
            } else if (action == Actions.CLEAR) {
90
√ 2
⟳ 2
                _clear(param);
91
√ 18
⟳ 8
            } else if (action == Actions.ASSERT_BALANCE_EQUALS) {
92
                _assertBalanceEquals(param);
93
√ 18
⟳ 8
            } else if (action == Actions.ASSERT_RESERVES_EQUALS) {
94
                _assertReservesEquals(param);
95
√ 18
⟳ 8
            } else if (action == Actions.ASSERT_DELTA_EQUALS) {
96
                _assertDeltaEquals(param);
97
√ 18
⟳ 8
            } else if (action == Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS) {
98
                _assertNonzeroDeltaCountEquals(param);
99
√ 18
⟳ 8
            } else if (action == Actions.TRANSFER_FROM) {
100
√ 2
⟳ 2
                _transferFrom(param);
101
√ 18
⟳ 8
            } else if (action == Actions.INITIALIZE) {
102
                _initialize(param);
103
√ 18
⟳ 8
            } else if (action == Actions.DONATE) {
104
√ 2
⟳ 2
                _donate(param);
105
√ 18
⟳ 6
            } else if (action == Actions.SWAP) {
106
√ 2
⟳ 2
                _swap(param);
107
√ 18
⟳ 6
            } else if (action == Actions.HARNESS_CALLBACK) {
108
√ 18
⟳ 6
                _harness_callback(param);
109
            } else {
110
                assert(false); //todo: remove
111
                revert ActionNotSupported();
112
            }
113
√ 13
⟳ 3
            assertOnException = false;
114
        }
115
√ 16
⟳ 16
        return "";
116
    }
117

                            
                        
118
    function executeActions(Actions[] memory actions, bytes[] memory params) external payable {
119
√ 13
⟳ 13
        manager.unlock(abi.encode(actions, params));
120
    }
121

                            
                        
122
    /// @notice Set this to "true" to raise an assertion error if the next action reverts.
123
    /// This can be used to create properties that assert that specific actions must never revert,
124
    //  however this function should be added to fuzzing blocklists if using multi-abi mode.
125
    function setAssertOnException(bool value) external {
126
        assertOnException = value;
127
    }
128

                            
                        
129
    function _harness_callback(bytes memory params) internal {
130
√ 27
⟳ 9
        (address harness, bytes memory cbParams) = abi.decode(params, (address, bytes));
131
√ 72
⟳ 24
        IActionsHarness(harness).routerCallback(cbParams, lastReturnData);
132
√ 45
⟳ 10
        lastReturnData = new bytes(0); // todo: we might need some data smuggled here if harness_callback is the last item in the actions list.
133
    }
134

                            
                        
135

                            
                        
136
    function _settle() internal {
137
√ 11
⟳ 11
        try manager.settle() returns (uint256 paid) {
138
√ 19
⟳ 19
            lastReturnData = abi.encode(paid);
139
        } catch Error(string memory reason) {
140
            emit log_named_string("revert reason", reason);
141
            assertFalse(assertOnException, "_settle reverted, but should not have");
142
            revert(reason);
143
        }
144
    }
145

                            
                        
146
    function _settleNative(bytes memory params) internal {
147
√ 2
⟳ 2
        uint256 amount = abi.decode(params, (uint256));
148
√ 12
⟳ 12
        try manager.settle{value: amount}() returns (uint256 paid) {
149
√ 19
⟳ 19
            lastReturnData = abi.encode(paid);
150
        } catch Error(string memory reason) {
151
            emit log_named_string("revert reason", reason);
152
            assertFalse(assertOnException, "_settleNative reverted, but should not have");
153
            revert(reason);
154
        }
155
    }
156

                            
                        
157
    function _settleFor(bytes memory params) internal {
158
√ 2
⟳ 2
        address recipient = abi.decode(params, (address));
159
√ 11
⟳ 11
        try manager.settleFor(recipient) returns (uint256 paid) {
160
            lastReturnData = abi.encode(paid);
161
        } catch Error(string memory reason) {
162
            emit log_named_string("revert reason", reason);
163
            assertFalse(assertOnException, "_settleFor reverted, but should not have");
164
            revert(reason);
165
        }
166
    }
167

                            
                        
168
    function _take(bytes memory params) internal {
169
√ 4
⟳ 4
        (Currency currency, address recipient, int128 amount) = abi.decode(params, (Currency, address, int128));
170
√ 10
⟳ 10
        try manager.take(currency, recipient, uint128(amount)) {
171
√ 1
⟳ 1
            lastReturnData = new bytes(0);
172
        } catch Error(string memory reason) {
173
            emit log_named_string("revert reason", reason);
174
            assertFalse(assertOnException, "_take reverted, but should not have");
175
            revert(reason);
176
        }        
177
    }
178

                            
                        
179
    function _prankTakeFrom(bytes memory params) internal {
180
        if(assertOnException) {
181
            revert AssertOnExceptionNotSupported();
182
        }
183
        (Currency currency, address from, address recipient, uint256 amount) =
184
            abi.decode(params, (Currency, address, address, uint256));
185
        vm.prank(from);
186
        manager.take(currency, recipient, amount);
187
√ 3
⟳ 3
        lastReturnData = new bytes(0);
188
    }
189

                            
                        
190
    function _sync(bytes memory params) internal {
191
√ 2
⟳ 2
        Currency currency = Currency.wrap(abi.decode(params, (address)));
192
√ 11
⟳ 11
        try manager.sync(currency) {
193
√ 1
⟳ 1
            lastReturnData = new bytes(0);
194
        } catch Error(string memory reason) {
195
            emit log_named_string("revert eason", reason);
196
            assertFalse(assertOnException, "_sync reverted, but should not have");
197
        }
198
    }
199

                            
                        
200
    function _mint(bytes memory params) internal {
201
√ 4
⟳ 4
        (address recipient, Currency currency, uint256 amount) = abi.decode(params, (address, Currency, uint256));
202
√ 12
⟳ 12
        try manager.mint(recipient, currency.toId(), amount) {
203
            lastReturnData = new bytes(0);
204
        } catch Error(string memory reason) {
205
            emit log_named_string("revert reason", reason);
206
            assertFalse(assertOnException, "_mint reverted, but should not have");
207
            revert(reason);
208
        }
209
    }
210

                            
                        
211
    function _burn(bytes memory params) internal {
212
√ 4
⟳ 4
        (address sender, Currency currency, uint256 amount) = abi.decode(params, (address, Currency, uint256));
213
√ 12
⟳ 12
        try manager.burn(sender, currency.toId(), amount){ 
214
            lastReturnData = new bytes(0);
215
        } catch Error(string memory reason) {
216
            emit log_named_string("revert reason", reason);
217
            assertFalse(assertOnException, "_burn reverted, but should not have");
218
            revert(reason);
219
        }
220
    }
221

                            
                        
222
    function _clear(bytes memory params) internal {
223
√ 4
⟳ 4
        (Currency currency, uint256 amount, bool measureGas, string memory gasSnapName) =
224
√ 1
⟳ 1
            abi.decode(params, (Currency, uint256, bool, string));
225
√ 10
⟳ 10
        try manager.clear(currency, amount) {
226
√ 1
⟳ 1
            lastReturnData = new bytes(0);
227
            // Disable gas snapshotting b/c echidna/medusa's engines can't handle the cheatcodes.
228
            // if (measureGas) snapLastCall(gasSnapName);
229
        } catch Error(string memory reason) {
230
            emit log_named_string("revert reason", reason);
231
            assertFalse(assertOnException, "_clear reverted, but should not have");
232
            revert(reason);
233
        }
234
    }
235

                            
                        
236
    function _assertBalanceEquals(bytes memory params) internal view {
237
        if(assertOnException) {
238
            revert AssertOnExceptionNotSupported();
239
        }
240
        (Currency currency, address user, uint256 expectedBalance) = abi.decode(params, (Currency, address, uint256));
241
        assertEq(currency.balanceOf(user), expectedBalance, "usertoken value incorrect");
242
    }
243

                            
                        
244
    function _assertReservesEquals(bytes memory params) internal view {
245
        if(assertOnException) {
246
            revert AssertOnExceptionNotSupported();
247
        }
248
        uint256 expectedReserves = abi.decode(params, (uint256));
249
        assertEq(manager.getSyncedReserves(), expectedReserves, "reserves value incorrect");
250
    }
251

                            
                        
252
    function _assertDeltaEquals(bytes memory params) internal view {
253
        if(assertOnException) {
254
            revert AssertOnExceptionNotSupported();
255
        }
256
        (Currency currency, address caller, int256 expectedDelta) = abi.decode(params, (Currency, address, int256));
257

                            
                        
258
        assertEq(manager.currencyDelta(caller, currency), expectedDelta, "delta value incorrect");
259
     }
260

                            
                        
261
    function _assertNonzeroDeltaCountEquals(bytes memory params) internal view {
262
        if(assertOnException) {
263
            revert AssertOnExceptionNotSupported();
264
        }
265
        (uint256 expectedCount) = abi.decode(params, (uint256));
266
        assertEq(manager.getNonzeroDeltaCount(), expectedCount, "nonzero delta count incorrect");
267
    }
268

                            
                        
269
    function _transferFrom(bytes memory params) internal {
270
√ 4
⟳ 4
        if(assertOnException) {
271
            revert AssertOnExceptionNotSupported();
272
        }
273
√ 4
⟳ 4
        (Currency currency, address from, address recipient, uint256 amount) =
274
√ 1
⟳ 1
            abi.decode(params, (Currency, address, address, uint256));
275
√ 7
⟳ 7
        MockERC20(Currency.unwrap(currency)).transferFrom(from, recipient, uint256(amount));
276
√ 1
⟳ 1
        lastReturnData = new bytes(0);
277
    }
278

                            
                        
279
    function _initialize(bytes memory params) internal {
280
        (address token0, address token1, int24 tickSpacing, uint160 initialPrice, uint24 initialFee) = 
281
            abi.decode(params, (address, address, int24, uint160, uint24));
282

                            
                        
283
        PoolKey memory k = PoolKey(Currency.wrap(token0), Currency.wrap(token1), initialFee, tickSpacing, IHooks(address(0)));
284
        
285
        try manager.initialize(k, initialPrice, new bytes(0)) returns (int24 tick ){
286
            lastReturnData = abi.encode(tick);
287
            return;
288
        } catch Error(string memory reason) {
289
            emit log_named_string("revert reason", reason);
290
            assertFalse(assertOnException, "_initialize reverted, but should not have");
291
            revert(reason);
292
        }
293
    }
294

                            
                        
295
    function _donate(bytes memory params) internal {
296
√ 4
⟳ 4
        (PoolKey memory key, uint256 amount0, uint256 amount1) = abi.decode(params, (PoolKey, uint256, uint256));
297

                            
                        
298
√ 8
⟳ 8
        try manager.donate(key, amount0, amount1, new bytes(0)) returns (BalanceDelta delta) { 
299
√ 19
⟳ 19
            lastReturnData = abi.encode(delta);
300
        } catch Error(string memory reason) {
301
            emit log_named_string("revert reason", reason);
302
            assertFalse(assertOnException, "_donate reverted, but should not have");
303
            revert(reason);
304
        }
305
    }
306

                            
                        
307
    function _modify_position(bytes memory params) internal {
308
√ 5
⟳ 5
        (PoolKey memory key, int24 tickLower, int24 tickUpper, int128 liquidity, uint256 salt) =
309
√ 1
⟳ 1
            abi.decode(params, (PoolKey, int24, int24, int128, uint256));
310

                            
                        
311
√ 46
⟳ 46
        IPoolManager.ModifyLiquidityParams memory modLiqParams = IPoolManager.ModifyLiquidityParams(
312
            tickLower, 
313
            tickUpper, 
314
            liquidity, 
315
            bytes32(salt));
316

                            
                        
317
√ 31
⟳ 31
        try manager.modifyLiquidity(key, modLiqParams, new bytes(0)) returns (BalanceDelta callerDelta, BalanceDelta feesAccrued) {
318
√ 19
⟳ 19
            lastReturnData = abi.encode(callerDelta, feesAccrued);
319
        } catch Error(string memory reason) {
320
            emit log_named_string("revert reason", reason);
321
            assertFalse(assertOnException, "_modify_position reverted, but should not have");
322
            revert(reason);
323
        }
324

                            
                        
325
    }
326

                            
                        
327
    function _swap(bytes memory params) internal {
328
√ 5
⟳ 5
        (bool zeroForOne, int256 amount, PoolKey memory poolKey, uint160 priceLimit) = abi.decode(params, (bool, int256, PoolKey, uint160));
329

                            
                        
330
√ 38
⟳ 38
        IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams(
331
            zeroForOne, 
332
            amount, 
333
            priceLimit
334
        );
335

                            
                        
336
√ 19
⟳ 19
        try manager.swap(poolKey, swapParams, new bytes(0)) returns (BalanceDelta swapDelta) {
337
√ 19
⟳ 38
            lastReturnData = abi.encode(swapDelta);
338
        } catch Error(string memory reason) {
339
            emit log_named_string("revert reason", reason);
340
            assertFalse(assertOnException, "_swap reverted, but should not have");
341
            revert(reason);
342
        }
343
    }
344

                            
                        
345
    fallback() external payable { }
346
    receive() external payable { }
347
}
348

                            
                        

Lines covered: 0 / 13 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {IHooks} from "../interfaces/IHooks.sol";
5
import {PoolKey} from "../types/PoolKey.sol";
6
import {BalanceDelta} from "../types/BalanceDelta.sol";
7
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
8
import {IPoolManager} from "../interfaces/IPoolManager.sol";
9

                            
                        
10
contract BaseTestHooks is IHooks {
11
    error HookNotImplemented();
12

                            
                        
13
    function beforeInitialize(
14
        address, /* sender **/
15
        PoolKey calldata, /* key **/
16
        uint160, /* sqrtPriceX96 **/
17
        bytes calldata /* hookData **/
18
    ) external virtual returns (bytes4) {
19
        revert HookNotImplemented();
20
    }
21

                            
                        
22
    function afterInitialize(
23
        address, /* sender **/
24
        PoolKey calldata, /* key **/
25
        uint160, /* sqrtPriceX96 **/
26
        int24, /* tick **/
27
        bytes calldata /* hookData **/
28
    ) external virtual returns (bytes4) {
29
        revert HookNotImplemented();
30
    }
31

                            
                        
32
    function beforeAddLiquidity(
33
        address, /* sender **/
34
        PoolKey calldata, /* key **/
35
        IPoolManager.ModifyLiquidityParams calldata, /* params **/
36
        bytes calldata /* hookData **/
37
    ) external virtual returns (bytes4) {
38
        revert HookNotImplemented();
39
    }
40

                            
                        
41
    function afterAddLiquidity(
42
        address, /* sender **/
43
        PoolKey calldata, /* key **/
44
        IPoolManager.ModifyLiquidityParams calldata, /* params **/
45
        BalanceDelta, /* delta **/
46
        bytes calldata /* hookData **/
47
    ) external virtual returns (bytes4, BalanceDelta) {
48
        revert HookNotImplemented();
49
    }
50

                            
                        
51
    function beforeRemoveLiquidity(
52
        address, /* sender **/
53
        PoolKey calldata, /* key **/
54
        IPoolManager.ModifyLiquidityParams calldata, /* params **/
55
        bytes calldata /* hookData **/
56
    ) external virtual returns (bytes4) {
57
        revert HookNotImplemented();
58
    }
59

                            
                        
60
    function afterRemoveLiquidity(
61
        address, /* sender **/
62
        PoolKey calldata, /* key **/
63
        IPoolManager.ModifyLiquidityParams calldata, /* params **/
64
        BalanceDelta, /* delta **/
65
        bytes calldata /* hookData **/
66
    ) external virtual returns (bytes4, BalanceDelta) {
67
        revert HookNotImplemented();
68
    }
69

                            
                        
70
    function beforeSwap(
71
        address, /* sender **/
72
        PoolKey calldata, /* key **/
73
        IPoolManager.SwapParams calldata, /* params **/
74
        bytes calldata /* hookData **/
75
    ) external virtual returns (bytes4, BeforeSwapDelta, uint24) {
76
        revert HookNotImplemented();
77
    }
78

                            
                        
79
    function afterSwap(
80
        address, /* sender **/
81
        PoolKey calldata, /* key **/
82
        IPoolManager.SwapParams calldata, /* params **/
83
        BalanceDelta, /* delta **/
84
        bytes calldata /* hookData **/
85
    ) external virtual returns (bytes4, int128) {
86
        revert HookNotImplemented();
87
    }
88

                            
                        
89
    function beforeDonate(
90
        address, /* sender **/
91
        PoolKey calldata, /* key **/
92
        uint256, /* amount0 **/
93
        uint256, /* amount1 **/
94
        bytes calldata /* hookData **/
95
    ) external virtual returns (bytes4) {
96
        revert HookNotImplemented();
97
    }
98

                            
                        
99
    function afterDonate(
100
        address, /* sender **/
101
        PoolKey calldata, /* key **/
102
        uint256, /* amount0 **/
103
        uint256, /* amount1 **/
104
        bytes calldata /* hookData **/
105
    ) external virtual returns (bytes4) {
106
        revert HookNotImplemented();
107
    }
108
}
109

                            
                        

Lines covered: 0 / 12 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Currency, CurrencyLibrary} from "../types/Currency.sol";
5

                            
                        
6
contract CurrencyTest {
7
    function transfer(Currency currency, address to, uint256 amount) external {
8
        currency.transfer(to, amount);
9
    }
10

                            
                        
11
    function balanceOfSelf(Currency currency) external view returns (uint256) {
12
        return currency.balanceOfSelf();
13
    }
14

                            
                        
15
    function balanceOf(Currency currency, address owner) external view returns (uint256) {
16
        return currency.balanceOf(owner);
17
    }
18

                            
                        
19
    function isNative(Currency currency) external pure returns (bool) {
20
        return currency.isNative();
21
    }
22

                            
                        
23
    function toId(Currency currency) external pure returns (uint256) {
24
        return currency.toId();
25
    }
26

                            
                        
27
    function fromId(uint256 id) external pure returns (Currency) {
28
        return CurrencyLibrary.fromId(id);
29
    }
30
}
31

                            
                        

Lines covered: 0 / 13 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Hooks} from "../libraries/Hooks.sol";
5
import {SafeCast} from "../libraries/SafeCast.sol";
6
import {IHooks} from "../interfaces/IHooks.sol";
7
import {IPoolManager} from "../interfaces/IPoolManager.sol";
8
import {PoolKey} from "../types/PoolKey.sol";
9
import {BeforeSwapDelta, toBeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
10
import {BalanceDelta} from "../types/BalanceDelta.sol";
11
import {Currency} from "../types/Currency.sol";
12
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
13
import {BaseTestHooks} from "./BaseTestHooks.sol";
14
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
15
import {Currency} from "../types/Currency.sol";
16

                            
                        
17
contract CustomCurveHook is BaseTestHooks {
18
    using Hooks for IHooks;
19
    using CurrencySettler for Currency;
20

                            
                        
21
    error AddLiquidityDirectToHook();
22

                            
                        
23
    IPoolManager immutable manager;
24

                            
                        
25
    constructor(IPoolManager _manager) {
26
        manager = _manager;
27
    }
28

                            
                        
29
    modifier onlyPoolManager() {
30
        require(msg.sender == address(manager));
31
        _;
32
    }
33

                            
                        
34
    function beforeSwap(
35
        address, /* sender **/
36
        PoolKey calldata key,
37
        IPoolManager.SwapParams calldata params,
38
        bytes calldata /* hookData **/
39
    ) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
40
        (Currency inputCurrency, Currency outputCurrency, uint256 amount) = _getInputOutputAndAmount(key, params);
41

                            
                        
42
        // this "custom curve" is a line, 1-1
43
        // take the full input amount, and give the full output amount
44
        manager.take(inputCurrency, address(this), amount);
45
        outputCurrency.settle(manager, address(this), amount, false);
46

                            
                        
47
        // return -amountSpecified as specified to no-op the concentrated liquidity swap
48
        BeforeSwapDelta hookDelta = toBeforeSwapDelta(int128(-params.amountSpecified), int128(params.amountSpecified));
49
        return (IHooks.beforeSwap.selector, hookDelta, 0);
50
    }
51

                            
                        
52
    function afterAddLiquidity(
53
        address, /* sender **/
54
        PoolKey calldata, /* key **/
55
        IPoolManager.ModifyLiquidityParams calldata, /* params **/
56
        BalanceDelta, /* delta **/
57
        bytes calldata /* hookData **/
58
    ) external view override onlyPoolManager returns (bytes4, BalanceDelta) {
59
        revert AddLiquidityDirectToHook();
60
    }
61

                            
                        
62
    function _getInputOutputAndAmount(PoolKey calldata key, IPoolManager.SwapParams calldata params)
63
        internal
64
        pure
65
        returns (Currency input, Currency output, uint256 amount)
66
    {
67
        (input, output) = params.zeroForOne ? (key.currency0, key.currency1) : (key.currency1, key.currency0);
68

                            
                        
69
        amount = params.amountSpecified < 0 ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);
70
    }
71
}
72

                            
                        

Lines covered: 0 / 25 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Hooks} from "../libraries/Hooks.sol";
5
import {SafeCast} from "../libraries/SafeCast.sol";
6
import {IHooks} from "../interfaces/IHooks.sol";
7
import {IPoolManager} from "../interfaces/IPoolManager.sol";
8
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
9
import {PoolKey} from "../types/PoolKey.sol";
10
import {BalanceDelta, toBalanceDelta} from "../types/BalanceDelta.sol";
11
import {Currency} from "../types/Currency.sol";
12
import {BaseTestHooks} from "./BaseTestHooks.sol";
13
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
14
import {Currency} from "../types/Currency.sol";
15
import {BeforeSwapDelta, toBeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
16

                            
                        
17
contract DeltaReturningHook is BaseTestHooks {
18
    using Hooks for IHooks;
19
    using CurrencySettler for Currency;
20

                            
                        
21
    IPoolManager immutable manager;
22

                            
                        
23
    int128 deltaSpecified;
24
    int128 deltaUnspecifiedBeforeSwap;
25
    int128 deltaUnspecifiedAfterSwap;
26

                            
                        
27
    constructor(IPoolManager _manager) {
28
        manager = _manager;
29
    }
30

                            
                        
31
    modifier onlyPoolManager() {
32
        require(msg.sender == address(manager));
33
        _;
34
    }
35

                            
                        
36
    function setDeltaSpecified(int128 delta) external {
37
        deltaSpecified = delta;
38
    }
39

                            
                        
40
    function setDeltaUnspecifiedBeforeSwap(int128 delta) external {
41
        deltaUnspecifiedBeforeSwap = delta;
42
    }
43

                            
                        
44
    function setDeltaUnspecifiedAfterSwap(int128 delta) external {
45
        deltaUnspecifiedAfterSwap = delta;
46
    }
47

                            
                        
48
    function beforeSwap(
49
        address, /* sender **/
50
        PoolKey calldata key,
51
        IPoolManager.SwapParams calldata params,
52
        bytes calldata /* hookData **/
53
    ) external override onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) {
54
        (Currency specifiedCurrency, Currency unspecifiedCurrency) = _sortCurrencies(key, params);
55

                            
                        
56
        if (deltaSpecified != 0) _settleOrTake(specifiedCurrency, deltaSpecified);
57
        if (deltaUnspecifiedBeforeSwap != 0) _settleOrTake(unspecifiedCurrency, deltaUnspecifiedBeforeSwap);
58

                            
                        
59
        BeforeSwapDelta beforeSwapDelta = toBeforeSwapDelta(deltaSpecified, deltaUnspecifiedBeforeSwap);
60

                            
                        
61
        return (IHooks.beforeSwap.selector, beforeSwapDelta, 0);
62
    }
63

                            
                        
64
    function afterSwap(
65
        address, /* sender **/
66
        PoolKey calldata key,
67
        IPoolManager.SwapParams calldata params,
68
        BalanceDelta, /* delta **/
69
        bytes calldata /* hookData **/
70
    ) external override onlyPoolManager returns (bytes4, int128) {
71
        (, Currency unspecifiedCurrency) = _sortCurrencies(key, params);
72
        _settleOrTake(unspecifiedCurrency, deltaUnspecifiedAfterSwap);
73

                            
                        
74
        return (IHooks.afterSwap.selector, deltaUnspecifiedAfterSwap);
75
    }
76

                            
                        
77
    function _sortCurrencies(PoolKey calldata key, IPoolManager.SwapParams calldata params)
78
        internal
79
        pure
80
        returns (Currency specified, Currency unspecified)
81
    {
82
        (specified, unspecified) = (params.zeroForOne == (params.amountSpecified < 0))
83
            ? (key.currency0, key.currency1)
84
            : (key.currency1, key.currency0);
85
    }
86

                            
                        
87
    function _settleOrTake(Currency currency, int128 delta) internal {
88
        // positive amount means positive delta for the hook, so it can take
89
        // negative it should settle
90
        if (delta > 0) {
91
            currency.take(manager, address(this), uint128(delta), false);
92
        } else {
93
            uint256 amount = uint256(-int256(delta));
94
            if (currency.isNative()) {
95
                manager.settle{value: amount}();
96
            } else {
97
                currency.settle(manager, address(this), amount, false);
98
            }
99
        }
100
    }
101
}
102

                            
                        

Lines covered: 0 / 10 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {BaseTestHooks} from "./BaseTestHooks.sol";
5
import {PoolKey} from "../types/PoolKey.sol";
6
import {IPoolManager} from "../interfaces/IPoolManager.sol";
7
import {IHooks} from "../interfaces/IHooks.sol";
8
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
9
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
10

                            
                        
11
contract DynamicFeesTestHook is BaseTestHooks {
12
    uint24 internal fee;
13
    IPoolManager manager;
14

                            
                        
15
    function setManager(IPoolManager _manager) external {
16
        manager = _manager;
17
    }
18

                            
                        
19
    function setFee(uint24 _fee) external {
20
        fee = _fee;
21
    }
22

                            
                        
23
    function afterInitialize(address, PoolKey calldata key, uint160, int24, bytes calldata)
24
        external
25
        override
26
        returns (bytes4)
27
    {
28
        manager.updateDynamicLPFee(key, fee);
29
        return IHooks.afterInitialize.selector;
30
    }
31

                            
                        
32
    function beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata, bytes calldata)
33
        external
34
        override
35
        returns (bytes4, BeforeSwapDelta, uint24)
36
    {
37
        manager.updateDynamicLPFee(key, fee);
38
        return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
39
    }
40

                            
                        
41
    function forcePoolFeeUpdate(PoolKey calldata _key, uint24 _fee) external {
42
        manager.updateDynamicLPFee(_key, _fee);
43
    }
44
}
45

                            
                        

Lines covered: 0 / 6 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {BaseTestHooks} from "./BaseTestHooks.sol";
5
import {PoolKey} from "../types/PoolKey.sol";
6
import {IPoolManager} from "../interfaces/IPoolManager.sol";
7
import {IHooks} from "../interfaces/IHooks.sol";
8
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
9
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
10

                            
                        
11
contract DynamicReturnFeeTestHook is BaseTestHooks {
12
    using LPFeeLibrary for uint24;
13

                            
                        
14
    uint24 internal fee;
15
    IPoolManager manager;
16

                            
                        
17
    function setManager(IPoolManager _manager) external {
18
        manager = _manager;
19
    }
20

                            
                        
21
    function setFee(uint24 _fee) external {
22
        fee = _fee;
23
    }
24

                            
                        
25
    function beforeSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata)
26
        external
27
        view
28
        override
29
        returns (bytes4, BeforeSwapDelta, uint24)
30
    {
31
        // attach the fee flag to `fee` to enable overriding the pool's stored fee
32
        return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, fee | LPFeeLibrary.OVERRIDE_FEE_FLAG);
33
    }
34

                            
                        
35
    function forcePoolFeeUpdate(PoolKey calldata _key, uint24 _fee) external {
36
        manager.updateDynamicLPFee(_key, _fee);
37
    }
38
}
39

                            
                        

Lines covered: 0 / 2 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
contract EmptyRevertContract {
5
    // a contract to simulate reverting with no returndata, to test that our error catching works
6
    fallback() external {
7
        revert();
8
    }
9
}
10

                            
                        

Lines covered: 0 / 16 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Hooks} from "../libraries/Hooks.sol";
5
import {IHooks} from "../interfaces/IHooks.sol";
6
import {IPoolManager} from "../interfaces/IPoolManager.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
9
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
10

                            
                        
11
contract EmptyTestHooks is IHooks {
12
    using Hooks for IHooks;
13

                            
                        
14
    constructor() {
15
        IHooks(this).validateHookPermissions(
16
            Hooks.Permissions({
17
                beforeInitialize: true,
18
                afterInitialize: true,
19
                beforeAddLiquidity: true,
20
                afterAddLiquidity: true,
21
                beforeRemoveLiquidity: true,
22
                afterRemoveLiquidity: true,
23
                beforeSwap: true,
24
                afterSwap: true,
25
                beforeDonate: true,
26
                afterDonate: true,
27
                beforeSwapReturnDelta: true,
28
                afterSwapReturnDelta: true,
29
                afterAddLiquidityReturnDelta: true,
30
                afterRemoveLiquidityReturnDelta: true
31
            })
32
        );
33
    }
34

                            
                        
35
    function beforeInitialize(address, PoolKey calldata, uint160, bytes calldata)
36
        external
37
        pure
38
        override
39
        returns (bytes4)
40
    {
41
        return IHooks.beforeInitialize.selector;
42
    }
43

                            
                        
44
    function afterInitialize(address, PoolKey calldata, uint160, int24, bytes calldata)
45
        external
46
        pure
47
        override
48
        returns (bytes4)
49
    {
50
        return IHooks.afterInitialize.selector;
51
    }
52

                            
                        
53
    function beforeAddLiquidity(address, PoolKey calldata, IPoolManager.ModifyLiquidityParams calldata, bytes calldata)
54
        external
55
        pure
56
        override
57
        returns (bytes4)
58
    {
59
        return IHooks.beforeAddLiquidity.selector;
60
    }
61

                            
                        
62
    function afterAddLiquidity(
63
        address,
64
        PoolKey calldata,
65
        IPoolManager.ModifyLiquidityParams calldata,
66
        BalanceDelta,
67
        bytes calldata
68
    ) external pure override returns (bytes4, BalanceDelta) {
69
        return (IHooks.afterAddLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA);
70
    }
71

                            
                        
72
    function beforeRemoveLiquidity(
73
        address,
74
        PoolKey calldata,
75
        IPoolManager.ModifyLiquidityParams calldata,
76
        bytes calldata
77
    ) external pure override returns (bytes4) {
78
        return IHooks.beforeRemoveLiquidity.selector;
79
    }
80

                            
                        
81
    function afterRemoveLiquidity(
82
        address,
83
        PoolKey calldata,
84
        IPoolManager.ModifyLiquidityParams calldata,
85
        BalanceDelta,
86
        bytes calldata
87
    ) external pure override returns (bytes4, BalanceDelta) {
88
        return (IHooks.afterRemoveLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA);
89
    }
90

                            
                        
91
    function beforeSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata)
92
        external
93
        pure
94
        override
95
        returns (bytes4, BeforeSwapDelta, uint24)
96
    {
97
        return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
98
    }
99

                            
                        
100
    function afterSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, BalanceDelta, bytes calldata)
101
        external
102
        pure
103
        override
104
        returns (bytes4, int128)
105
    {
106
        return (IHooks.afterSwap.selector, 0);
107
    }
108

                            
                        
109
    function beforeDonate(address, PoolKey calldata, uint256, uint256, bytes calldata)
110
        external
111
        pure
112
        override
113
        returns (bytes4)
114
    {
115
        return IHooks.beforeDonate.selector;
116
    }
117

                            
                        
118
    function afterDonate(address, PoolKey calldata, uint256, uint256, bytes calldata)
119
        external
120
        pure
121
        override
122
        returns (bytes4)
123
    {
124
        return IHooks.afterDonate.selector;
125
    }
126
}
127

                            
                        

Lines covered: 0 / 27 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Hooks} from "../libraries/Hooks.sol";
5
import {SafeCast} from "../libraries/SafeCast.sol";
6
import {IHooks} from "../interfaces/IHooks.sol";
7
import {IPoolManager} from "../interfaces/IPoolManager.sol";
8
import {PoolKey} from "../types/PoolKey.sol";
9
import {BalanceDelta, toBalanceDelta} from "../types/BalanceDelta.sol";
10
import {Currency} from "../types/Currency.sol";
11
import {BaseTestHooks} from "./BaseTestHooks.sol";
12

                            
                        
13
contract FeeTakingHook is BaseTestHooks {
14
    using Hooks for IHooks;
15
    using SafeCast for uint256;
16
    using SafeCast for int128;
17

                            
                        
18
    IPoolManager immutable manager;
19

                            
                        
20
    constructor(IPoolManager _manager) {
21
        manager = _manager;
22
    }
23

                            
                        
24
    modifier onlyPoolManager() {
25
        require(msg.sender == address(manager));
26
        _;
27
    }
28

                            
                        
29
    uint128 public constant LIQUIDITY_FEE = 543; // 543/10000 = 5.43%
30
    uint128 public constant SWAP_FEE_BIPS = 123; // 123/10000 = 1.23%
31
    uint128 public constant TOTAL_BIPS = 10000;
32

                            
                        
33
    function afterSwap(
34
        address, /* sender **/
35
        PoolKey calldata key,
36
        IPoolManager.SwapParams calldata params,
37
        BalanceDelta delta,
38
        bytes calldata /* hookData **/
39
    ) external override onlyPoolManager returns (bytes4, int128) {
40
        // fee will be in the unspecified token of the swap
41
        bool specifiedTokenIs0 = (params.amountSpecified < 0 == params.zeroForOne);
42
        (Currency feeCurrency, int128 swapAmount) =
43
            (specifiedTokenIs0) ? (key.currency1, delta.amount1()) : (key.currency0, delta.amount0());
44
        // if fee is on output, get the absolute output amount
45
        if (swapAmount < 0) swapAmount = -swapAmount;
46

                            
                        
47
        uint256 feeAmount = uint128(swapAmount) * SWAP_FEE_BIPS / TOTAL_BIPS;
48
        manager.take(feeCurrency, address(this), feeAmount);
49

                            
                        
50
        return (IHooks.afterSwap.selector, feeAmount.toInt128());
51
    }
52

                            
                        
53
    function afterRemoveLiquidity(
54
        address, /* sender **/
55
        PoolKey calldata key,
56
        IPoolManager.ModifyLiquidityParams calldata, /* params **/
57
        BalanceDelta delta,
58
        bytes calldata /* hookData **/
59
    ) external override onlyPoolManager returns (bytes4, BalanceDelta) {
60
        assert(delta.amount0() >= 0 && delta.amount1() >= 0);
61

                            
                        
62
        uint128 feeAmount0 = uint128(delta.amount0()) * LIQUIDITY_FEE / TOTAL_BIPS;
63
        uint128 feeAmount1 = uint128(delta.amount1()) * LIQUIDITY_FEE / TOTAL_BIPS;
64

                            
                        
65
        manager.take(key.currency0, address(this), feeAmount0);
66
        manager.take(key.currency1, address(this), feeAmount1);
67

                            
                        
68
        return (IHooks.afterRemoveLiquidity.selector, toBalanceDelta(int128(feeAmount0), int128(feeAmount1)));
69
    }
70

                            
                        
71
    function afterAddLiquidity(
72
        address, /* sender **/
73
        PoolKey calldata key,
74
        IPoolManager.ModifyLiquidityParams calldata, /* params **/
75
        BalanceDelta delta,
76
        bytes calldata /* hookData **/
77
    ) external override onlyPoolManager returns (bytes4, BalanceDelta) {
78
        assert(delta.amount0() <= 0 && delta.amount1() <= 0);
79

                            
                        
80
        uint128 feeAmount0 = uint128(-delta.amount0()) * LIQUIDITY_FEE / TOTAL_BIPS;
81
        uint128 feeAmount1 = uint128(-delta.amount1()) * LIQUIDITY_FEE / TOTAL_BIPS;
82

                            
                        
83
        manager.take(key.currency0, address(this), feeAmount0);
84
        manager.take(key.currency1, address(this), feeAmount1);
85

                            
                        
86
        return (IHooks.afterAddLiquidity.selector, toBalanceDelta(int128(feeAmount0), int128(feeAmount1)));
87
    }
88
}
89

                            
                        

Lines covered: 0 / 62 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Vm} from "forge-std/Vm.sol";
5
import {StdUtils} from "forge-std/StdUtils.sol";
6

                            
                        
7
import {IPoolManager} from "../interfaces/IPoolManager.sol";
8
import {PoolKey} from "../types/PoolKey.sol";
9
import {BalanceDelta} from "../types/BalanceDelta.sol";
10
import {TickMath} from "../libraries/TickMath.sol";
11
import {Pool} from "../libraries/Pool.sol";
12
import {PoolModifyLiquidityTest} from "./PoolModifyLiquidityTest.sol";
13
import {LiquidityAmounts} from "../../test/utils/LiquidityAmounts.sol";
14
import {SafeCast} from "../../src/libraries/SafeCast.sol";
15

                            
                        
16
contract Fuzzers is StdUtils {
17
    using SafeCast for uint256;
18

                            
                        
19
    Vm internal constant _vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
20

                            
                        
21
    function boundLiquidityDelta(PoolKey memory key, int256 liquidityDeltaUnbounded, int256 liquidityMaxByAmount)
22
        internal
23
        pure
24
        returns (int256)
25
    {
26
        int256 liquidityMaxPerTick = int256(uint256(Pool.tickSpacingToMaxLiquidityPerTick(key.tickSpacing)));
27

                            
                        
28
        // Finally bound the seeded liquidity by either the max per tick, or by the amount allowed in the position range.
29
        int256 liquidityMax = liquidityMaxByAmount > liquidityMaxPerTick ? liquidityMaxPerTick : liquidityMaxByAmount;
30
        _vm.assume(liquidityMax != 0);
31
        return bound(liquidityDeltaUnbounded, 1, liquidityMax);
32
    }
33

                            
                        
34
    // Uses tickSpacingToMaxLiquidityPerTick/2 as one of the possible bounds.
35
    // Potentially adjust this value to be more strict for positions that touch the same tick.
36
    function boundLiquidityDeltaTightly(
37
        PoolKey memory key,
38
        int256 liquidityDeltaUnbounded,
39
        int256 liquidityMaxByAmount,
40
        uint256 maxPositions
41
    ) internal pure returns (int256) {
42
        // Divide by half to bound liquidity more. TODO: Probably a better way to do this.
43
        int256 liquidityMaxTightBound =
44
            int256(uint256(Pool.tickSpacingToMaxLiquidityPerTick(key.tickSpacing)) / maxPositions);
45

                            
                        
46
        // Finally bound the seeded liquidity by either the max per tick, or by the amount allowed in the position range.
47
        int256 liquidityMax =
48
            liquidityMaxByAmount > liquidityMaxTightBound ? liquidityMaxTightBound : liquidityMaxByAmount;
49
        _vm.assume(liquidityMax != 0);
50
        return bound(liquidityDeltaUnbounded, 1, liquidityMax);
51
    }
52

                            
                        
53
    function getLiquidityDeltaFromAmounts(int24 tickLower, int24 tickUpper, uint160 sqrtPriceX96)
54
        internal
55
        pure
56
        returns (int256)
57
    {
58
        // First get the maximum amount0 and maximum amount1 that can be deposited at this range.
59
        (uint256 maxAmount0, uint256 maxAmount1) = LiquidityAmounts.getAmountsForLiquidity(
60
            sqrtPriceX96,
61
            TickMath.getSqrtPriceAtTick(tickLower),
62
            TickMath.getSqrtPriceAtTick(tickUpper),
63
            uint128(type(int128).max)
64
        );
65

                            
                        
66
        // Compare the max amounts (defined by the range of the position) to the max amount constrained by the type container.
67
        // The true maximum should be the minimum of the two.
68
        // (ie If the position range allows a deposit of more then int128.max in any token, then here we cap it at int128.max.)
69

                            
                        
70
        uint256 amount0 = uint256(type(uint128).max / 2);
71
        uint256 amount1 = uint256(type(uint128).max / 2);
72

                            
                        
73
        maxAmount0 = maxAmount0 > amount0 ? amount0 : maxAmount0;
74
        maxAmount1 = maxAmount1 > amount1 ? amount1 : maxAmount1;
75

                            
                        
76
        int256 liquidityMaxByAmount = uint256(
77
            LiquidityAmounts.getLiquidityForAmounts(
78
                sqrtPriceX96,
79
                TickMath.getSqrtPriceAtTick(tickLower),
80
                TickMath.getSqrtPriceAtTick(tickUpper),
81
                maxAmount0,
82
                maxAmount1
83
            )
84
        ).toInt256();
85

                            
                        
86
        return liquidityMaxByAmount;
87
    }
88

                            
                        
89
    function boundTicks(int24 tickLower, int24 tickUpper, int24 tickSpacing) internal pure returns (int24, int24) {
90
        tickLower = int24(
91
            bound(
92
                int256(tickLower),
93
                int256(TickMath.minUsableTick(tickSpacing)),
94
                int256(TickMath.maxUsableTick(tickSpacing))
95
            )
96
        );
97
        tickUpper = int24(
98
            bound(
99
                int256(tickUpper),
100
                int256(TickMath.minUsableTick(tickSpacing)),
101
                int256(TickMath.maxUsableTick(tickSpacing))
102
            )
103
        );
104

                            
                        
105
        // round down ticks
106
        tickLower = (tickLower / tickSpacing) * tickSpacing;
107
        tickUpper = (tickUpper / tickSpacing) * tickSpacing;
108

                            
                        
109
        (tickLower, tickUpper) = tickLower < tickUpper ? (tickLower, tickUpper) : (tickUpper, tickLower);
110

                            
                        
111
        if (tickLower == tickUpper) {
112
            if (tickLower != TickMath.minUsableTick(tickSpacing)) tickLower = tickLower - tickSpacing;
113
            else tickUpper = tickUpper + tickSpacing;
114
        }
115

                            
                        
116
        return (tickLower, tickUpper);
117
    }
118

                            
                        
119
    function boundTicks(PoolKey memory key, int24 tickLower, int24 tickUpper) internal pure returns (int24, int24) {
120
        return boundTicks(tickLower, tickUpper, key.tickSpacing);
121
    }
122

                            
                        
123
    function createRandomSqrtPriceX96(int24 tickSpacing, int256 seed) internal pure returns (uint160) {
124
        int256 min = int256(TickMath.minUsableTick(tickSpacing));
125
        int256 max = int256(TickMath.maxUsableTick(tickSpacing));
126
        int256 randomTick = bound(seed, min + 1, max - 1);
127
        return TickMath.getSqrtPriceAtTick(int24(randomTick));
128
    }
129

                            
                        
130
    /// @dev Obtain fuzzed and bounded parameters for creating liquidity
131
    /// @param key The pool key
132
    /// @param params IPoolManager.ModifyLiquidityParams Note that these parameters are unbounded
133
    /// @param sqrtPriceX96 The current sqrt price
134
    function createFuzzyLiquidityParams(
135
        PoolKey memory key,
136
        IPoolManager.ModifyLiquidityParams memory params,
137
        uint160 sqrtPriceX96
138
    ) internal pure returns (IPoolManager.ModifyLiquidityParams memory result) {
139
        (result.tickLower, result.tickUpper) = boundTicks(key, params.tickLower, params.tickUpper);
140
        int256 liquidityDeltaFromAmounts =
141
            getLiquidityDeltaFromAmounts(result.tickLower, result.tickUpper, sqrtPriceX96);
142
        result.liquidityDelta = boundLiquidityDelta(key, params.liquidityDelta, liquidityDeltaFromAmounts);
143
    }
144

                            
                        
145
    // Creates liquidity parameters with a stricter bound. Should be used if multiple positions being intitialized on the pool, with potential for tick overlap.
146
    function createFuzzyLiquidityParamsWithTightBound(
147
        PoolKey memory key,
148
        IPoolManager.ModifyLiquidityParams memory params,
149
        uint160 sqrtPriceX96,
150
        uint256 maxPositions
151
    ) internal pure returns (IPoolManager.ModifyLiquidityParams memory result) {
152
        (result.tickLower, result.tickUpper) = boundTicks(key, params.tickLower, params.tickUpper);
153
        int256 liquidityDeltaFromAmounts =
154
            getLiquidityDeltaFromAmounts(result.tickLower, result.tickUpper, sqrtPriceX96);
155

                            
                        
156
        result.liquidityDelta =
157
            boundLiquidityDeltaTightly(key, params.liquidityDelta, liquidityDeltaFromAmounts, maxPositions);
158
    }
159

                            
                        
160
    function createFuzzyLiquidity(
161
        PoolModifyLiquidityTest modifyLiquidityRouter,
162
        PoolKey memory key,
163
        IPoolManager.ModifyLiquidityParams memory params,
164
        uint160 sqrtPriceX96,
165
        bytes memory hookData
166
    ) internal returns (IPoolManager.ModifyLiquidityParams memory result, BalanceDelta delta) {
167
        result = createFuzzyLiquidityParams(key, params, sqrtPriceX96);
168
        delta = modifyLiquidityRouter.modifyLiquidity(key, result, hookData);
169
    }
170

                            
                        
171
    // There exists possible positions in the pool, so we tighten the boundaries of liquidity.
172
    function createFuzzyLiquidityWithTightBound(
173
        PoolModifyLiquidityTest modifyLiquidityRouter,
174
        PoolKey memory key,
175
        IPoolManager.ModifyLiquidityParams memory params,
176
        uint160 sqrtPriceX96,
177
        bytes memory hookData,
178
        uint256 maxPositions
179
    ) internal returns (IPoolManager.ModifyLiquidityParams memory result, BalanceDelta delta) {
180
        result = createFuzzyLiquidityParamsWithTightBound(key, params, sqrtPriceX96, maxPositions);
181
        delta = modifyLiquidityRouter.modifyLiquidity(key, result, hookData);
182
    }
183
}
184

                            
                        

Lines covered: 0 / 31 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Hooks} from "../libraries/Hooks.sol";
5
import {IHooks} from "../interfaces/IHooks.sol";
6

                            
                        
7
contract HooksTest {
8
    using Hooks for IHooks;
9

                            
                        
10
    function validateHookPermissions(address hookAddress, Hooks.Permissions calldata params) external pure {
11
        IHooks(hookAddress).validateHookPermissions(params);
12
    }
13

                            
                        
14
    function isValidHookAddress(address hookAddress, uint24 fee) external pure returns (bool) {
15
        return IHooks(hookAddress).isValidHookAddress(fee);
16
    }
17

                            
                        
18
    function shouldCallBeforeInitialize(address hookAddress) external pure returns (bool) {
19
        return IHooks(hookAddress).hasPermission(Hooks.BEFORE_INITIALIZE_FLAG);
20
    }
21

                            
                        
22
    function shouldCallAfterInitialize(address hookAddress) external pure returns (bool) {
23
        return IHooks(hookAddress).hasPermission(Hooks.AFTER_INITIALIZE_FLAG);
24
    }
25

                            
                        
26
    function shouldCallBeforeSwap(address hookAddress) external pure returns (bool) {
27
        return IHooks(hookAddress).hasPermission(Hooks.BEFORE_SWAP_FLAG);
28
    }
29

                            
                        
30
    function shouldCallAfterSwap(address hookAddress) external pure returns (bool) {
31
        return IHooks(hookAddress).hasPermission(Hooks.AFTER_SWAP_FLAG);
32
    }
33

                            
                        
34
    function shouldCallBeforeAddLiquidity(address hookAddress) external pure returns (bool) {
35
        return IHooks(hookAddress).hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG);
36
    }
37

                            
                        
38
    function shouldCallAfterAddLiquidity(address hookAddress) external pure returns (bool) {
39
        return IHooks(hookAddress).hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG);
40
    }
41

                            
                        
42
    function shouldCallBeforeRemoveLiquidity(address hookAddress) external pure returns (bool) {
43
        return IHooks(hookAddress).hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG);
44
    }
45

                            
                        
46
    function shouldCallAfterRemoveLiquidity(address hookAddress) external pure returns (bool) {
47
        return IHooks(hookAddress).hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG);
48
    }
49

                            
                        
50
    function shouldCallBeforeDonate(address hookAddress) external pure returns (bool) {
51
        return IHooks(hookAddress).hasPermission(Hooks.BEFORE_DONATE_FLAG);
52
    }
53

                            
                        
54
    function shouldCallAfterDonate(address hookAddress) external pure returns (bool) {
55
        return IHooks(hookAddress).hasPermission(Hooks.AFTER_DONATE_FLAG);
56
    }
57

                            
                        
58
    function getGasCostOfShouldCall(address hookAddress) external view returns (uint256) {
59
        uint256 gasBefore = gasleft();
60
        IHooks(hookAddress).hasPermission(Hooks.BEFORE_SWAP_FLAG);
61
        return gasBefore - gasleft();
62
    }
63

                            
                        
64
    function getGasCostOfValidateHookAddress(address hookAddress, Hooks.Permissions calldata params)
65
        external
66
        view
67
        returns (uint256)
68
    {
69
        uint256 gasBefore = gasleft();
70
        IHooks(hookAddress).validateHookPermissions(params);
71
        return gasBefore - gasleft();
72
    }
73
}
74

                            
                        

Lines covered: 0 / 3 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {LiquidityMath} from "../libraries/LiquidityMath.sol";
5

                            
                        
6
contract LiquidityMathTest {
7
    function addDelta(uint128 x, int128 y) external pure returns (uint128 z) {
8
        return LiquidityMath.addDelta(x, y);
9
    }
10
}
11

                            
                        

Lines covered: 0 / 15 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Proxy} from "@openzeppelin/contracts/proxy/Proxy.sol";
5

                            
                        
6
/// @notice Mock contract that tracks the number of calls to various functions by selector
7
/// @dev allows for proxying to an implementation contract
8
///  if real logic or return values are needed
9
contract MockContract is Proxy {
10
    mapping(bytes32 => uint256) public calls;
11
    mapping(bytes32 => mapping(bytes => uint256)) public callParams;
12

                            
                        
13
    /// @notice If set, delegatecall to implementation after tracking call
14
    address internal impl;
15

                            
                        
16
    function timesCalledSelector(bytes32 selector) public view returns (uint256) {
17
        return calls[selector];
18
    }
19

                            
                        
20
    function timesCalled(string calldata fnSig) public view returns (uint256) {
21
        bytes32 selector = bytes32(uint256(keccak256(bytes(fnSig))) & (type(uint256).max << 224));
22
        return calls[selector];
23
    }
24

                            
                        
25
    function calledWithSelector(bytes32 selector, bytes calldata params) public view returns (bool) {
26
        return callParams[selector][params[1:]] > 0; // Drop 0x byte string prefix
27
    }
28

                            
                        
29
    function calledWith(string calldata fnSig, bytes calldata params) public view returns (bool) {
30
        bytes32 selector = bytes32(uint256(keccak256(bytes(fnSig))) & (type(uint256).max << 224));
31
        return callParams[selector][params[1:]] > 0; // Drop 0x byte string prefix
32
    }
33

                            
                        
34
    /// @notice exposes implementation contract address
35
    function _implementation() internal view override returns (address) {
36
        return impl;
37
    }
38

                            
                        
39
    function setImplementation(address _impl) external {
40
        impl = _impl;
41
    }
42

                            
                        
43
    /// @notice Captures calls by selector
44
    function _beforeFallback() internal {
45
        bytes32 selector = bytes32(msg.data[:5]);
46
        bytes memory params = msg.data[5:];
47
        calls[selector]++;
48
        callParams[selector][params]++;
49
    }
50
}
51

                            
                        

Lines covered: 0 / 4 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {ERC6909Claims} from "../ERC6909Claims.sol";
6
import {Currency} from "../types/Currency.sol";
7

                            
                        
8
/// @notice Mock contract for testing ERC6909Claims
9
contract MockERC6909Claims is ERC6909Claims {
10
    /// @notice mocked mint logic
11
    function mint(address to, uint256 id, uint256 amount) public {
12
        _mint(to, id, amount);
13
    }
14

                            
                        
15
    /// @notice mocked burn logic
16
    function burn(uint256 id, uint256 amount) public {
17
        _burn(msg.sender, id, amount);
18
    }
19

                            
                        
20
    /// @notice mocked burn logic without checking sender allowance
21
    function burnFrom(address from, uint256 id, uint256 amount) public {
22
        _burnFrom(from, id, amount);
23
    }
24
}
25

                            
                        

Lines covered: 0 / 55 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Hooks} from "../libraries/Hooks.sol";
5
import {IHooks} from "../interfaces/IHooks.sol";
6
import {IPoolManager} from "../interfaces/IPoolManager.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
9
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
10
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
11

                            
                        
12
contract MockHooks is IHooks {
13
    using PoolIdLibrary for PoolKey;
14
    using Hooks for IHooks;
15

                            
                        
16
    bytes public beforeInitializeData;
17
    bytes public afterInitializeData;
18
    bytes public beforeAddLiquidityData;
19
    bytes public afterAddLiquidityData;
20
    bytes public beforeRemoveLiquidityData;
21
    bytes public afterRemoveLiquidityData;
22
    bytes public beforeSwapData;
23
    bytes public afterSwapData;
24
    bytes public beforeDonateData;
25
    bytes public afterDonateData;
26

                            
                        
27
    mapping(bytes4 => bytes4) public returnValues;
28

                            
                        
29
    mapping(PoolId => uint16) public lpFees;
30

                            
                        
31
    function beforeInitialize(address, PoolKey calldata, uint160, bytes calldata hookData)
32
        external
33
        override
34
        returns (bytes4)
35
    {
36
        beforeInitializeData = hookData;
37
        bytes4 selector = MockHooks.beforeInitialize.selector;
38
        return returnValues[selector] == bytes4(0) ? selector : returnValues[selector];
39
    }
40

                            
                        
41
    function afterInitialize(address, PoolKey calldata, uint160, int24, bytes calldata hookData)
42
        external
43
        override
44
        returns (bytes4)
45
    {
46
        afterInitializeData = hookData;
47
        bytes4 selector = MockHooks.afterInitialize.selector;
48
        return returnValues[selector] == bytes4(0) ? selector : returnValues[selector];
49
    }
50

                            
                        
51
    function beforeAddLiquidity(
52
        address,
53
        PoolKey calldata,
54
        IPoolManager.ModifyLiquidityParams calldata,
55
        bytes calldata hookData
56
    ) external override returns (bytes4) {
57
        beforeAddLiquidityData = hookData;
58
        bytes4 selector = MockHooks.beforeAddLiquidity.selector;
59
        return returnValues[selector] == bytes4(0) ? selector : returnValues[selector];
60
    }
61

                            
                        
62
    function afterAddLiquidity(
63
        address,
64
        PoolKey calldata,
65
        IPoolManager.ModifyLiquidityParams calldata,
66
        BalanceDelta,
67
        bytes calldata hookData
68
    ) external override returns (bytes4, BalanceDelta) {
69
        afterAddLiquidityData = hookData;
70
        bytes4 selector = MockHooks.afterAddLiquidity.selector;
71
        return (returnValues[selector] == bytes4(0) ? selector : returnValues[selector], BalanceDeltaLibrary.ZERO_DELTA);
72
    }
73

                            
                        
74
    function beforeRemoveLiquidity(
75
        address,
76
        PoolKey calldata,
77
        IPoolManager.ModifyLiquidityParams calldata,
78
        bytes calldata hookData
79
    ) external override returns (bytes4) {
80
        beforeRemoveLiquidityData = hookData;
81
        bytes4 selector = MockHooks.beforeRemoveLiquidity.selector;
82
        return returnValues[selector] == bytes4(0) ? selector : returnValues[selector];
83
    }
84

                            
                        
85
    function afterRemoveLiquidity(
86
        address,
87
        PoolKey calldata,
88
        IPoolManager.ModifyLiquidityParams calldata,
89
        BalanceDelta,
90
        bytes calldata hookData
91
    ) external override returns (bytes4, BalanceDelta) {
92
        afterRemoveLiquidityData = hookData;
93
        bytes4 selector = MockHooks.afterRemoveLiquidity.selector;
94
        return (returnValues[selector] == bytes4(0) ? selector : returnValues[selector], BalanceDeltaLibrary.ZERO_DELTA);
95
    }
96

                            
                        
97
    function beforeSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata hookData)
98
        external
99
        override
100
        returns (bytes4, BeforeSwapDelta, uint24)
101
    {
102
        beforeSwapData = hookData;
103
        bytes4 selector = MockHooks.beforeSwap.selector;
104
        return (
105
            returnValues[selector] == bytes4(0) ? selector : returnValues[selector],
106
            BeforeSwapDeltaLibrary.ZERO_DELTA,
107
            0
108
        );
109
    }
110

                            
                        
111
    function afterSwap(
112
        address,
113
        PoolKey calldata,
114
        IPoolManager.SwapParams calldata,
115
        BalanceDelta,
116
        bytes calldata hookData
117
    ) external override returns (bytes4, int128) {
118
        afterSwapData = hookData;
119
        bytes4 selector = MockHooks.afterSwap.selector;
120
        return (returnValues[selector] == bytes4(0) ? selector : returnValues[selector], 0);
121
    }
122

                            
                        
123
    function beforeDonate(address, PoolKey calldata, uint256, uint256, bytes calldata hookData)
124
        external
125
        override
126
        returns (bytes4)
127
    {
128
        beforeDonateData = hookData;
129
        bytes4 selector = MockHooks.beforeDonate.selector;
130
        return returnValues[selector] == bytes4(0) ? selector : returnValues[selector];
131
    }
132

                            
                        
133
    function afterDonate(address, PoolKey calldata, uint256, uint256, bytes calldata hookData)
134
        external
135
        override
136
        returns (bytes4)
137
    {
138
        afterDonateData = hookData;
139
        bytes4 selector = MockHooks.afterDonate.selector;
140
        return returnValues[selector] == bytes4(0) ? selector : returnValues[selector];
141
    }
142

                            
                        
143
    function setReturnValue(bytes4 key, bytes4 value) external {
144
        returnValues[key] = value;
145
    }
146

                            
                        
147
    function setlpFee(PoolKey calldata key, uint16 value) external {
148
        lpFees[key.toId()] = value;
149
    }
150
}
151

                            
                        

Lines covered: 0 / 21 (0.0%)

1
// SPDX-License-Identifier: GPL-3.0-or-later
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5

                            
                        
6
/// @dev This token contract simulates the ERC20 representation of a native token where on `transfer` and `transferFrom` the native balances are modified using a precompile
7
contract NativeERC20 is Test {
8
    string public name = "NativeERC20";
9
    string public symbol = "NERC20";
10
    uint8 public decimals = 18;
11

                            
                        
12
    event Approval(address indexed src, address indexed guy, uint256 wad);
13
    event Transfer(address indexed src, address indexed dst, uint256 wad);
14

                            
                        
15
    mapping(address => mapping(address => uint256)) public allowance;
16

                            
                        
17
    function totalSupply() public view returns (uint256) {
18
        return address(this).balance;
19
    }
20

                            
                        
21
    function approve(address guy, uint256 wad) public returns (bool) {
22
        allowance[msg.sender][guy] = wad;
23
        emit Approval(msg.sender, guy, wad);
24
        return true;
25
    }
26

                            
                        
27
    function transfer(address dst, uint256 wad) public returns (bool) {
28
        return transferFrom(msg.sender, dst, wad);
29
    }
30

                            
                        
31
    function transferFrom(address src, address dst, uint256 wad) public returns (bool) {
32
        require(src.balance >= wad);
33

                            
                        
34
        if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {
35
            require(allowance[src][msg.sender] >= wad, "");
36
            allowance[src][msg.sender] -= wad;
37
        }
38

                            
                        
39
        vm.deal(src, src.balance - wad);
40
        vm.deal(dst, dst.balance + wad);
41

                            
                        
42
        emit Transfer(src, dst, wad);
43

                            
                        
44
        return true;
45
    }
46

                            
                        
47
    function balanceOf(address account) external view returns (uint256) {
48
        return account.balance;
49
    }
50
}
51

                            
                        

Lines covered: 0 / 14 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {NoDelegateCall} from "../NoDelegateCall.sol";
5

                            
                        
6
contract NoDelegateCallTest is NoDelegateCall {
7
    function canBeDelegateCalled() public view returns (uint256) {
8
        return block.timestamp / 5;
9
    }
10

                            
                        
11
    function cannotBeDelegateCalled() public view noDelegateCall returns (uint256) {
12
        return block.timestamp / 5;
13
    }
14

                            
                        
15
    function getGasCostOfCanBeDelegateCalled() external view returns (uint256) {
16
        uint256 gasBefore = gasleft();
17
        canBeDelegateCalled();
18
        return gasBefore - gasleft();
19
    }
20

                            
                        
21
    function getGasCostOfCannotBeDelegateCalled() external view returns (uint256) {
22
        uint256 gasBefore = gasleft();
23
        cannotBeDelegateCalled();
24
        return gasBefore - gasleft();
25
    }
26

                            
                        
27
    function callsIntoNoDelegateCallFunction() external view {
28
        noDelegateCallPrivate();
29
    }
30

                            
                        
31
    function noDelegateCallPrivate() private view noDelegateCall {}
32
}
33

                            
                        

Lines covered: 1 / 12 (8.3%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Currency} from "../types/Currency.sol";
5
import {BalanceDelta, toBalanceDelta} from "../types/BalanceDelta.sol";
6
import {IPoolManager} from "../interfaces/IPoolManager.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8
import {PoolTestBase} from "./PoolTestBase.sol";
9
import {SafeCast} from "../libraries/SafeCast.sol";
10
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
11

                            
                        
12
contract PoolClaimsTest is PoolTestBase {
13
    using CurrencySettler for Currency;
14
    using SafeCast for uint256;
15

                            
                        
16
√ 27
    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
17

                            
                        
18
    struct CallbackData {
19
        address sender;
20
        address user;
21
        Currency currency;
22
        uint256 amount;
23
        bool deposit;
24
    }
25

                            
                        
26
    /// @notice Convert ERC20 into a claimable 6909
27
    function deposit(Currency currency, address user, uint256 amount) external payable {
28
        manager.unlock(abi.encode(CallbackData(msg.sender, user, currency, amount, true)));
29
    }
30

                            
                        
31
    /// @notice Redeem claimable 6909 for ERC20
32
    function withdraw(Currency currency, address user, uint256 amount) external payable {
33
        manager.unlock(abi.encode(CallbackData(msg.sender, user, currency, amount, false)));
34
    }
35

                            
                        
36
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
37
        require(msg.sender == address(manager));
38

                            
                        
39
        CallbackData memory data = abi.decode(rawData, (CallbackData));
40

                            
                        
41
        if (data.deposit) {
42
            data.currency.take(manager, data.user, data.amount, true); // mint 6909
43
            data.currency.settle(manager, data.user, data.amount, false); // transfer ERC20
44
        } else {
45
            data.currency.settle(manager, data.user, data.amount, true); // burn 6909
46
            data.currency.take(manager, data.user, data.amount, false); // claim ERC20
47
        }
48

                            
                        
49
        return abi.encode(0);
50
    }
51
}
52

                            
                        

Lines covered: 1 / 23 (4.3%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Currency, CurrencyLibrary} from "../types/Currency.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {PoolKey} from "../types/PoolKey.sol";
7
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
8
import {PoolTestBase} from "./PoolTestBase.sol";
9
import {IHooks} from "../interfaces/IHooks.sol";
10
import {Hooks} from "../libraries/Hooks.sol";
11
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
12

                            
                        
13
contract PoolDonateTest is PoolTestBase {
14
    using CurrencySettler for Currency;
15
    using Hooks for IHooks;
16

                            
                        
17
√ 27
    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
18

                            
                        
19
    struct CallbackData {
20
        address sender;
21
        PoolKey key;
22
        uint256 amount0;
23
        uint256 amount1;
24
        bytes hookData;
25
    }
26

                            
                        
27
    function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes memory hookData)
28
        external
29
        payable
30
        returns (BalanceDelta delta)
31
    {
32
        delta = abi.decode(
33
            manager.unlock(abi.encode(CallbackData(msg.sender, key, amount0, amount1, hookData))), (BalanceDelta)
34
        );
35

                            
                        
36
        uint256 ethBalance = address(this).balance;
37
        if (ethBalance > 0) {
38
            CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance);
39
        }
40
    }
41

                            
                        
42
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
43
        require(msg.sender == address(manager));
44

                            
                        
45
        CallbackData memory data = abi.decode(rawData, (CallbackData));
46

                            
                        
47
        (,, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender, address(this));
48
        (,, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender, address(this));
49

                            
                        
50
        require(deltaBefore0 == 0, "deltaBefore0 is not 0");
51
        require(deltaBefore1 == 0, "deltaBefore1 is not 0");
52

                            
                        
53
        BalanceDelta delta = manager.donate(data.key, data.amount0, data.amount1, data.hookData);
54

                            
                        
55
        (,, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this));
56
        (,, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this));
57

                            
                        
58
        require(deltaAfter0 == -int256(data.amount0), "deltaAfter0 is not equal to -int256(data.amount0)");
59
        require(deltaAfter1 == -int256(data.amount1), "deltaAfter1 is not equal to -int256(data.amount1)");
60

                            
                        
61
        if (deltaAfter0 < 0) data.key.currency0.settle(manager, data.sender, uint256(-deltaAfter0), false);
62
        if (deltaAfter1 < 0) data.key.currency1.settle(manager, data.sender, uint256(-deltaAfter1), false);
63
        if (deltaAfter0 > 0) data.key.currency0.take(manager, data.sender, uint256(deltaAfter0), false);
64
        if (deltaAfter1 > 0) data.key.currency1.take(manager, data.sender, uint256(deltaAfter1), false);
65

                            
                        
66
        return abi.encode(delta);
67
    }
68
}
69

                            
                        

Lines covered: 0 / 5 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {IPoolManager} from "../interfaces/IPoolManager.sol";
5
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
6

                            
                        
7
contract PoolEmptyUnlockTest is IUnlockCallback {
8
    event UnlockCallback();
9

                            
                        
10
    IPoolManager manager;
11

                            
                        
12
    constructor(IPoolManager _manager) {
13
        manager = _manager;
14
    }
15

                            
                        
16
    function unlock() external {
17
        manager.unlock("");
18
    }
19

                            
                        
20
    /// @notice Called by the pool manager on `msg.sender` when the manager is unlocked
21
    function unlockCallback(bytes calldata) external override returns (bytes memory) {
22
        emit UnlockCallback();
23
        return "";
24
    }
25
}
26

                            
                        

Lines covered: 1 / 30 (3.3%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {CurrencyLibrary, Currency} from "../types/Currency.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {BalanceDelta} from "../types/BalanceDelta.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8
import {PoolIdLibrary} from "../types/PoolId.sol";
9
import {PoolTestBase} from "./PoolTestBase.sol";
10
import {IHooks} from "../interfaces/IHooks.sol";
11
import {Hooks} from "../libraries/Hooks.sol";
12
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
13
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
14
import {StateLibrary} from "../libraries/StateLibrary.sol";
15

                            
                        
16
contract PoolModifyLiquidityTest is PoolTestBase {
17
    using CurrencySettler for Currency;
18
    using Hooks for IHooks;
19
    using LPFeeLibrary for uint24;
20
    using PoolIdLibrary for PoolKey;
21
    using StateLibrary for IPoolManager;
22

                            
                        
23
√ 27
    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
24

                            
                        
25
    struct CallbackData {
26
        address sender;
27
        PoolKey key;
28
        IPoolManager.ModifyLiquidityParams params;
29
        bytes hookData;
30
        bool settleUsingBurn;
31
        bool takeClaims;
32
    }
33

                            
                        
34
    function modifyLiquidity(
35
        PoolKey memory key,
36
        IPoolManager.ModifyLiquidityParams memory params,
37
        bytes memory hookData
38
    ) external payable returns (BalanceDelta delta) {
39
        delta = modifyLiquidity(key, params, hookData, false, false);
40
    }
41

                            
                        
42
    function modifyLiquidity(
43
        PoolKey memory key,
44
        IPoolManager.ModifyLiquidityParams memory params,
45
        bytes memory hookData,
46
        bool settleUsingBurn,
47
        bool takeClaims
48
    ) public payable returns (BalanceDelta delta) {
49
        delta = abi.decode(
50
            manager.unlock(abi.encode(CallbackData(msg.sender, key, params, hookData, settleUsingBurn, takeClaims))),
51
            (BalanceDelta)
52
        );
53

                            
                        
54
        uint256 ethBalance = address(this).balance;
55
        if (ethBalance > 0) {
56
            CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance);
57
        }
58
    }
59

                            
                        
60
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
61
        require(msg.sender == address(manager));
62

                            
                        
63
        CallbackData memory data = abi.decode(rawData, (CallbackData));
64

                            
                        
65
        uint128 liquidityBefore = manager.getPosition(
66
            data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt
67
        ).liquidity;
68

                            
                        
69
        (BalanceDelta delta,) = manager.modifyLiquidity(data.key, data.params, data.hookData);
70

                            
                        
71
        uint128 liquidityAfter = manager.getPosition(
72
            data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt
73
        ).liquidity;
74

                            
                        
75
        (,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender, address(this));
76
        (,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender, address(this));
77

                            
                        
78
        require(
79
            int128(liquidityBefore) + data.params.liquidityDelta == int128(liquidityAfter), "liquidity change incorrect"
80
        );
81

                            
                        
82
        if (data.params.liquidityDelta < 0) {
83
            assert(delta0 > 0 || delta1 > 0);
84
            assert(!(delta0 < 0 || delta1 < 0));
85
        } else if (data.params.liquidityDelta > 0) {
86
            assert(delta0 < 0 || delta1 < 0);
87
            assert(!(delta0 > 0 || delta1 > 0));
88
        }
89

                            
                        
90
        if (delta0 < 0) data.key.currency0.settle(manager, data.sender, uint256(-delta0), data.settleUsingBurn);
91
        if (delta1 < 0) data.key.currency1.settle(manager, data.sender, uint256(-delta1), data.settleUsingBurn);
92
        if (delta0 > 0) data.key.currency0.take(manager, data.sender, uint256(delta0), data.takeClaims);
93
        if (delta1 > 0) data.key.currency1.take(manager, data.sender, uint256(delta1), data.takeClaims);
94

                            
                        
95
        return abi.encode(delta);
96
    }
97
}
98

                            
                        

Lines covered: 1 / 19 (5.3%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {CurrencyLibrary, Currency} from "../types/Currency.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {BalanceDelta} from "../types/BalanceDelta.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8
import {PoolIdLibrary} from "../types/PoolId.sol";
9
import {PoolTestBase} from "./PoolTestBase.sol";
10
import {IHooks} from "../interfaces/IHooks.sol";
11
import {Hooks} from "../libraries/Hooks.sol";
12
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
13
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
14
import {Constants} from "../../test/utils/Constants.sol";
15

                            
                        
16
contract PoolModifyLiquidityTestNoChecks is PoolTestBase {
17
    using CurrencySettler for Currency;
18
    using Hooks for IHooks;
19
    using LPFeeLibrary for uint24;
20
    using PoolIdLibrary for PoolKey;
21

                            
                        
22
√ 27
    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
23

                            
                        
24
    struct CallbackData {
25
        address sender;
26
        PoolKey key;
27
        IPoolManager.ModifyLiquidityParams params;
28
        bytes hookData;
29
        bool settleUsingBurn;
30
        bool takeClaims;
31
    }
32

                            
                        
33
    function modifyLiquidity(
34
        PoolKey memory key,
35
        IPoolManager.ModifyLiquidityParams memory params,
36
        bytes memory hookData
37
    ) external payable returns (BalanceDelta delta) {
38
        delta = modifyLiquidity(key, params, hookData, false, false);
39
    }
40

                            
                        
41
    function modifyLiquidity(
42
        PoolKey memory key,
43
        IPoolManager.ModifyLiquidityParams memory params,
44
        bytes memory hookData,
45
        bool settleUsingBurn,
46
        bool takeClaims
47
    ) public payable returns (BalanceDelta delta) {
48
        delta = abi.decode(
49
            manager.unlock(abi.encode(CallbackData(msg.sender, key, params, hookData, settleUsingBurn, takeClaims))),
50
            (BalanceDelta)
51
        );
52

                            
                        
53
        uint256 ethBalance = address(this).balance;
54
        if (ethBalance > 0) {
55
            CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance);
56
        }
57
    }
58

                            
                        
59
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
60
        require(msg.sender == address(manager));
61

                            
                        
62
        CallbackData memory data = abi.decode(rawData, (CallbackData));
63

                            
                        
64
        (BalanceDelta delta,) = manager.modifyLiquidity(data.key, data.params, data.hookData);
65

                            
                        
66
        int256 delta0 = delta.amount0();
67
        int256 delta1 = delta.amount1();
68

                            
                        
69
        if (delta0 < 0) data.key.currency0.settle(manager, data.sender, uint256(-delta0), data.settleUsingBurn);
70
        if (delta1 < 0) data.key.currency1.settle(manager, data.sender, uint256(-delta1), data.settleUsingBurn);
71
        if (delta0 > 0) data.key.currency0.take(manager, data.sender, uint256(delta0), data.takeClaims);
72
        if (delta1 > 0) data.key.currency1.take(manager, data.sender, uint256(delta1), data.takeClaims);
73

                            
                        
74
        return abi.encode(delta);
75
    }
76
}
77

                            
                        

Lines covered: 10 / 118 (8.5%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {IPoolManager} from "../interfaces/IPoolManager.sol";
5
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
6
import {PoolTestBase} from "./PoolTestBase.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8
import {Constants} from "../../test/utils/Constants.sol";
9
import {Test} from "forge-std/Test.sol";
10
import {BalanceDelta} from "../types/BalanceDelta.sol";
11
import {Currency} from "../types/Currency.sol";
12
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
13
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
14
import {StateLibrary} from "../libraries/StateLibrary.sol";
15
import {TransientStateLibrary} from "../libraries/TransientStateLibrary.sol";
16

                            
                        
17
enum Action {
18
    NESTED_SELF_UNLOCK,
19
    NESTED_EXECUTOR_UNLOCK,
20
    SWAP_AND_SETTLE,
21
    DONATE_AND_SETTLE,
22
    ADD_LIQUIDITY_AND_SETTLE,
23
    REMOVE_LIQUIDITY_AND_SETTLE,
24
    INITIALIZE
25
}
26

                            
                        
27
contract PoolNestedActionsTest is Test, IUnlockCallback {
28
    using StateLibrary for IPoolManager;
29
    using TransientStateLibrary for IPoolManager;
30

                            
                        
31
    IPoolManager manager;
32
√ 13
    NestedActionExecutor public executor;
33
    address user;
34

                            
                        
35
    constructor(IPoolManager _manager) {
36
√ 1
        manager = _manager;
37
√ 3
        user = msg.sender;
38
√ 7
        executor = new NestedActionExecutor(manager, user);
39
    }
40

                            
                        
41
    function unlock(bytes calldata data) external {
42
        manager.unlock(data);
43
    }
44

                            
                        
45
    /// @notice Called by the pool manager on `msg.sender` when the manager is unlocked
46
    function unlockCallback(bytes calldata data) external override returns (bytes memory) {
47
        Action[] memory actions = abi.decode(data, (Action[]));
48
        if (actions.length == 1 && actions[0] == Action.NESTED_SELF_UNLOCK) {
49
            _nestedUnlock();
50
        } else {
51
            executor.execute(actions);
52
        }
53
        return "";
54
    }
55

                            
                        
56
    function _nestedUnlock() internal {
57
        bool unlocked = manager.isUnlocked();
58
        assertEq(unlocked, true);
59
        vm.expectRevert(abi.encodeWithSelector(IPoolManager.AlreadyUnlocked.selector));
60
        manager.unlock("");
61
        unlocked = manager.isUnlocked();
62
        assertEq(unlocked, true);
63
    }
64
}
65

                            
                        
66
contract NestedActionExecutor is Test, PoolTestBase {
67
    using StateLibrary for IPoolManager;
68
    using TransientStateLibrary for IPoolManager;
69
    using CurrencySettler for Currency;
70
    using PoolIdLibrary for PoolKey;
71

                            
                        
72
    PoolKey internal key;
73
    address user;
74

                            
                        
75
    error KeyNotSet();
76

                            
                        
77
    IPoolManager.ModifyLiquidityParams internal ADD_LIQUIDITY_PARAMS =
78
√ 2
        IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: 0});
79

                            
                        
80
    IPoolManager.ModifyLiquidityParams internal REMOVE_LIQUIDITY_PARAMS =
81
√ 18
        IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: -1e18, salt: 0});
82

                            
                        
83
    IPoolManager.SwapParams internal SWAP_PARAMS =
84
√ 13
        IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: Constants.SQRT_PRICE_1_2});
85

                            
                        
86
√ 1
    uint256 internal DONATE_AMOUNT0 = 12345e6;
87
√ 1
    uint256 internal DONATE_AMOUNT1 = 98765e4;
88

                            
                        
89
    constructor(IPoolManager _manager, address _user) PoolTestBase(_manager) {
90
√ 1
        user = _user;
91
    }
92

                            
                        
93
    function setKey(PoolKey memory _key) external {
94
        key = _key;
95
    }
96

                            
                        
97
    function execute(Action[] memory actions) public {
98
        if (Currency.unwrap(key.currency0) == address(0)) revert KeyNotSet();
99
        for (uint256 i = 0; i < actions.length; i++) {
100
            Action action = actions[i];
101
            if (action == Action.NESTED_EXECUTOR_UNLOCK) _nestedUnlock();
102
            else if (action == Action.SWAP_AND_SETTLE) _swap(msg.sender);
103
            else if (action == Action.ADD_LIQUIDITY_AND_SETTLE) _addLiquidity(msg.sender);
104
            else if (action == Action.REMOVE_LIQUIDITY_AND_SETTLE) _removeLiquidity(msg.sender);
105
            else if (action == Action.DONATE_AND_SETTLE) _donate(msg.sender);
106
            else if (action == Action.INITIALIZE) _initialize();
107
        }
108
    }
109

                            
                        
110
    function _nestedUnlock() internal {
111
        bool unlocked = manager.isUnlocked();
112
        assertEq(unlocked, true);
113
        vm.expectRevert(abi.encodeWithSelector(IPoolManager.AlreadyUnlocked.selector));
114
        manager.unlock("");
115
        unlocked = manager.isUnlocked();
116
        assertEq(unlocked, true);
117
    }
118

                            
                        
119
    function _swap(address caller) internal {
120
        bool unlocked = manager.isUnlocked();
121
        assertEq(unlocked, true);
122
        (,, int256 deltaCallerBefore0) = _fetchBalances(key.currency0, user, caller);
123
        (,, int256 deltaCallerBefore1) = _fetchBalances(key.currency1, user, caller);
124
        (,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
125
        (,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this));
126

                            
                        
127
        BalanceDelta delta = manager.swap(key, SWAP_PARAMS, "");
128

                            
                        
129
        (,, int256 deltaCallerAfter0) = _fetchBalances(key.currency0, user, caller);
130
        (,, int256 deltaCallerAfter1) = _fetchBalances(key.currency1, user, caller);
131
        (,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this));
132
        (,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this));
133

                            
                        
134
        assertEq(deltaCallerBefore0, deltaCallerAfter0, "Caller delta 0");
135
        assertEq(deltaCallerBefore1, deltaCallerAfter1, "Caller delta 1");
136
        assertEq(deltaThisBefore0 + SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0");
137
        assertEq(deltaThisBefore1 + 98, deltaThisAfter1, "Executor delta 1");
138
        assertEq(delta.amount0(), deltaThisAfter0, "Swap delta 0");
139
        assertEq(delta.amount1(), deltaThisAfter1, "Swap delta 1");
140

                            
                        
141
        key.currency0.settle(manager, user, uint256(-deltaThisAfter0), false);
142
        key.currency1.take(manager, user, uint256(deltaThisAfter1), false);
143
    }
144

                            
                        
145
    function _addLiquidity(address caller) internal {
146
        bool unlocked = manager.isUnlocked();
147
        assertEq(unlocked, true);
148
        (,, int256 deltaCallerBefore0) = _fetchBalances(key.currency0, user, caller);
149
        (,, int256 deltaCallerBefore1) = _fetchBalances(key.currency1, user, caller);
150
        (,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
151
        (,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this));
152

                            
                        
153
        (BalanceDelta delta,) = manager.modifyLiquidity(key, ADD_LIQUIDITY_PARAMS, "");
154

                            
                        
155
        (,, int256 deltaCallerAfter0) = _fetchBalances(key.currency0, user, caller);
156
        (,, int256 deltaCallerAfter1) = _fetchBalances(key.currency1, user, caller);
157
        (,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this));
158
        (,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this));
159

                            
                        
160
        assertEq(deltaCallerBefore0, deltaCallerAfter0, "Caller delta 0");
161
        assertEq(deltaCallerBefore1, deltaCallerAfter1, "Caller delta 1");
162
        assertEq(deltaThisBefore0 + delta.amount0(), deltaThisAfter0, "Executor delta 0");
163
        assertEq(deltaThisBefore1 + delta.amount1(), deltaThisAfter1, "Executor delta 1");
164

                            
                        
165
        key.currency0.settle(manager, user, uint256(-deltaThisAfter0), false);
166
        key.currency1.settle(manager, user, uint256(-deltaThisAfter1), false);
167
    }
168

                            
                        
169
    // cannot remove non-existent liquidity - need to perform an add before this removal
170
    function _removeLiquidity(address caller) internal {
171
        bool unlocked = manager.isUnlocked();
172
        assertEq(unlocked, true);
173
        (,, int256 deltaCallerBefore0) = _fetchBalances(key.currency0, user, caller);
174
        (,, int256 deltaCallerBefore1) = _fetchBalances(key.currency1, user, caller);
175
        (,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
176
        (,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this));
177

                            
                        
178
        (BalanceDelta delta,) = manager.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, "");
179

                            
                        
180
        (,, int256 deltaCallerAfter0) = _fetchBalances(key.currency0, user, caller);
181
        (,, int256 deltaCallerAfter1) = _fetchBalances(key.currency1, user, caller);
182
        (,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this));
183
        (,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this));
184

                            
                        
185
        assertEq(deltaCallerBefore0, deltaCallerAfter0, "Caller delta 0");
186
        assertEq(deltaCallerBefore1, deltaCallerAfter1, "Caller delta 1");
187
        assertEq(deltaThisBefore0 + delta.amount0(), deltaThisAfter0, "Executor delta 0");
188
        assertEq(deltaThisBefore1 + delta.amount1(), deltaThisAfter1, "Executor delta 1");
189

                            
                        
190
        key.currency0.take(manager, user, uint256(deltaThisAfter0), false);
191
        key.currency1.take(manager, user, uint256(deltaThisAfter1), false);
192
    }
193

                            
                        
194
    function _donate(address caller) internal {
195
        bool unlocked = manager.isUnlocked();
196
        assertEq(unlocked, true);
197
        (,, int256 deltaCallerBefore0) = _fetchBalances(key.currency0, user, caller);
198
        (,, int256 deltaCallerBefore1) = _fetchBalances(key.currency1, user, caller);
199
        (,, int256 deltaThisBefore0) = _fetchBalances(key.currency0, user, address(this));
200
        (,, int256 deltaThisBefore1) = _fetchBalances(key.currency1, user, address(this));
201

                            
                        
202
        BalanceDelta delta = manager.donate(key, DONATE_AMOUNT0, DONATE_AMOUNT1, "");
203

                            
                        
204
        (,, int256 deltaCallerAfter0) = _fetchBalances(key.currency0, user, caller);
205
        (,, int256 deltaCallerAfter1) = _fetchBalances(key.currency1, user, caller);
206
        (,, int256 deltaThisAfter0) = _fetchBalances(key.currency0, user, address(this));
207
        (,, int256 deltaThisAfter1) = _fetchBalances(key.currency1, user, address(this));
208

                            
                        
209
        assertEq(deltaCallerBefore0, deltaCallerAfter0, "Caller delta 0");
210
        assertEq(deltaCallerBefore1, deltaCallerAfter1, "Caller delta 1");
211
        assertEq(deltaThisBefore0 - int256(DONATE_AMOUNT0), deltaThisAfter0, "Executor delta 0");
212
        assertEq(deltaThisBefore1 - int256(DONATE_AMOUNT1), deltaThisAfter1, "Executor delta 1");
213
        assertEq(-delta.amount0(), int256(DONATE_AMOUNT0), "Donate delta 0");
214
        assertEq(-delta.amount1(), int256(DONATE_AMOUNT1), "Donate delta 1");
215

                            
                        
216
        key.currency0.settle(manager, user, uint256(-deltaThisAfter0), false);
217
        key.currency1.settle(manager, user, uint256(-deltaThisAfter1), false);
218
    }
219

                            
                        
220
    function _initialize() internal {
221
        bool unlocked = manager.isUnlocked();
222
        assertEq(unlocked, true);
223
        key.tickSpacing = 50;
224
        PoolId id = key.toId();
225
        (uint256 price,,,) = manager.getSlot0(id);
226
        assertEq(price, 0);
227
        manager.initialize(key, Constants.SQRT_PRICE_1_2, Constants.ZERO_BYTES);
228
        (price,,,) = manager.getSlot0(id);
229
        assertEq(price, Constants.SQRT_PRICE_1_2);
230
    }
231

                            
                        
232
    // This will never actually be used - its just to allow us to use the PoolTestBase helper contact
233
    function unlockCallback(bytes calldata) external pure override returns (bytes memory) {
234
        return "";
235
    }
236
}
237

                            
                        

Lines covered: 1 / 6 (16.7%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {IPoolManager} from "../interfaces/IPoolManager.sol";
5
import {PoolKey} from "../types/PoolKey.sol";
6
import {PoolTestBase} from "./PoolTestBase.sol";
7

                            
                        
8
contract PoolSettleTest is PoolTestBase {
9
√ 27
    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
10

                            
                        
11
    function settle() external payable {
12
        manager.unlock("");
13
    }
14

                            
                        
15
    function unlockCallback(bytes calldata) external returns (bytes memory) {
16
        require(msg.sender == address(manager));
17

                            
                        
18
        manager.settle{value: address(this).balance}();
19

                            
                        
20
        return abi.encode(0);
21
    }
22
}
23

                            
                        

Lines covered: 1 / 39 (2.6%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {CurrencyLibrary, Currency} from "../types/Currency.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8
import {IHooks} from "../interfaces/IHooks.sol";
9
import {Hooks} from "../libraries/Hooks.sol";
10
import {PoolTestBase} from "./PoolTestBase.sol";
11
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
12

                            
                        
13
contract PoolSwapTest is PoolTestBase {
14
    using CurrencySettler for Currency;
15
    using Hooks for IHooks;
16

                            
                        
17
√ 27
    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
18

                            
                        
19
    error NoSwapOccurred();
20

                            
                        
21
    struct CallbackData {
22
        address sender;
23
        TestSettings testSettings;
24
        PoolKey key;
25
        IPoolManager.SwapParams params;
26
        bytes hookData;
27
    }
28

                            
                        
29
    struct TestSettings {
30
        bool takeClaims;
31
        bool settleUsingBurn;
32
    }
33

                            
                        
34
    function swap(
35
        PoolKey memory key,
36
        IPoolManager.SwapParams memory params,
37
        TestSettings memory testSettings,
38
        bytes memory hookData
39
    ) external payable returns (BalanceDelta delta) {
40
        delta = abi.decode(
41
            manager.unlock(abi.encode(CallbackData(msg.sender, testSettings, key, params, hookData))), (BalanceDelta)
42
        );
43

                            
                        
44
        uint256 ethBalance = address(this).balance;
45
        if (ethBalance > 0) CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance);
46
    }
47

                            
                        
48
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
49
        require(msg.sender == address(manager));
50

                            
                        
51
        CallbackData memory data = abi.decode(rawData, (CallbackData));
52

                            
                        
53
        (,, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender, address(this));
54
        (,, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender, address(this));
55

                            
                        
56
        require(deltaBefore0 == 0, "deltaBefore0 is not equal to 0");
57
        require(deltaBefore1 == 0, "deltaBefore1 is not equal to 0");
58

                            
                        
59
        BalanceDelta delta = manager.swap(data.key, data.params, data.hookData);
60

                            
                        
61
        (,, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this));
62
        (,, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this));
63

                            
                        
64
        if (data.params.zeroForOne) {
65
            if (data.params.amountSpecified < 0) {
66
                // exact input, 0 for 1
67
                require(
68
                    deltaAfter0 >= data.params.amountSpecified,
69
                    "deltaAfter0 is not greater than or equal to data.params.amountSpecified"
70
                );
71
                require(delta.amount0() == deltaAfter0, "delta.amount0() is not equal to deltaAfter0");
72
                require(deltaAfter1 >= 0, "deltaAfter1 is not greater than or equal to 0");
73
            } else {
74
                // exact output, 0 for 1
75
                require(deltaAfter0 <= 0, "deltaAfter0 is not less than or equal to zero");
76
                require(delta.amount1() == deltaAfter1, "delta.amount1() is not equal to deltaAfter1");
77
                require(
78
                    deltaAfter1 <= data.params.amountSpecified,
79
                    "deltaAfter1 is not less than or equal to data.params.amountSpecified"
80
                );
81
            }
82
        } else {
83
            if (data.params.amountSpecified < 0) {
84
                // exact input, 1 for 0
85
                require(
86
                    deltaAfter1 >= data.params.amountSpecified,
87
                    "deltaAfter1 is not greater than or equal to data.params.amountSpecified"
88
                );
89
                require(delta.amount1() == deltaAfter1, "delta.amount1() is not equal to deltaAfter1");
90
                require(deltaAfter0 >= 0, "deltaAfter0 is not greater than or equal to 0");
91
            } else {
92
                // exact output, 1 for 0
93
                require(deltaAfter1 <= 0, "deltaAfter1 is not less than or equal to 0");
94
                require(delta.amount0() == deltaAfter0, "delta.amount0() is not equal to deltaAfter0");
95
                require(
96
                    deltaAfter0 <= data.params.amountSpecified,
97
                    "deltaAfter0 is not less than or equal to data.params.amountSpecified"
98
                );
99
            }
100
        }
101

                            
                        
102
        if (deltaAfter0 < 0) {
103
            data.key.currency0.settle(manager, data.sender, uint256(-deltaAfter0), data.testSettings.settleUsingBurn);
104
        }
105
        if (deltaAfter1 < 0) {
106
            data.key.currency1.settle(manager, data.sender, uint256(-deltaAfter1), data.testSettings.settleUsingBurn);
107
        }
108
        if (deltaAfter0 > 0) {
109
            data.key.currency0.take(manager, data.sender, uint256(deltaAfter0), data.testSettings.takeClaims);
110
        }
111
        if (deltaAfter1 > 0) {
112
            data.key.currency1.take(manager, data.sender, uint256(deltaAfter1), data.testSettings.takeClaims);
113
        }
114

                            
                        
115
        return abi.encode(delta);
116
    }
117
}
118

                            
                        

Lines covered: 1 / 17 (5.9%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Currency} from "../types/Currency.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {PoolKey} from "../types/PoolKey.sol";
7
import {PoolTestBase} from "./PoolTestBase.sol";
8
import {SafeCast} from "../libraries/SafeCast.sol";
9
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
10

                            
                        
11
contract PoolTakeTest is PoolTestBase {
12
    using CurrencySettler for Currency;
13
    using SafeCast for uint256;
14

                            
                        
15
√ 27
    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
16

                            
                        
17
    struct CallbackData {
18
        address sender;
19
        PoolKey key;
20
        uint256 amount0;
21
        uint256 amount1;
22
    }
23

                            
                        
24
    function take(PoolKey memory key, uint256 amount0, uint256 amount1) external payable {
25
        manager.unlock(abi.encode(CallbackData(msg.sender, key, amount0, amount1)));
26
    }
27

                            
                        
28
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
29
        require(msg.sender == address(manager));
30

                            
                        
31
        CallbackData memory data = abi.decode(rawData, (CallbackData));
32

                            
                        
33
        if (data.amount0 > 0) _testTake(data.key.currency0, data.sender, data.amount0);
34
        if (data.amount1 > 0) _testTake(data.key.currency1, data.sender, data.amount1);
35

                            
                        
36
        return abi.encode(0);
37
    }
38

                            
                        
39
    function _testTake(Currency currency, address sender, uint256 amount) internal {
40
        (uint256 userBalBefore, uint256 pmBalBefore, int256 deltaBefore) =
41
            _fetchBalances(currency, sender, address(this));
42
        require(deltaBefore == 0, "deltaBefore is not equal to 0");
43

                            
                        
44
        currency.take(manager, sender, amount, false);
45

                            
                        
46
        (uint256 userBalAfter, uint256 pmBalAfter, int256 deltaAfter) = _fetchBalances(currency, sender, address(this));
47

                            
                        
48
        require(deltaAfter == -amount.toInt128(), "deltaAfter is not equal to -amount.toInt128()");
49

                            
                        
50
        require(
51
            userBalAfter - userBalBefore == amount,
52
            "the difference between userBalAfter and userBalBefore is not equal to amount"
53
        );
54
        require(
55
            pmBalBefore - pmBalAfter == amount,
56
            "the difference between pmBalBefore and pmBalAfter is not equal to amount"
57
        );
58

                            
                        
59
        currency.settle(manager, sender, amount, false);
60
    }
61
}
62

                            
                        

Lines covered: 1 / 6 (16.7%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Currency} from "../types/Currency.sol";
5
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
6

                            
                        
7
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
8
import {IPoolManager} from "../interfaces/IPoolManager.sol";
9

                            
                        
10
import {StateLibrary} from "../libraries/StateLibrary.sol";
11
import {TransientStateLibrary} from "../libraries/TransientStateLibrary.sol";
12

                            
                        
13
abstract contract PoolTestBase is IUnlockCallback {
14
    using StateLibrary for IPoolManager;
15
    using TransientStateLibrary for IPoolManager;
16

                            
                        
17
    IPoolManager public immutable manager;
18

                            
                        
19
    constructor(IPoolManager _manager) {
20
√ 29
        manager = _manager;
21
    }
22

                            
                        
23
    function _fetchBalances(Currency currency, address user, address deltaHolder)
24
        internal
25
        view
26
        returns (uint256 userBalance, uint256 poolBalance, int256 delta)
27
    {
28
        userBalance = currency.balanceOf(user);
29
        poolBalance = currency.balanceOf(address(manager));
30
        delta = manager.currencyDelta(deltaHolder, currency);
31
    }
32
}
33

                            
                        

Lines covered: 7 / 21 (33.3%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {IProtocolFeeController} from "../interfaces/IProtocolFeeController.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8

                            
                        
9
√ 17
contract ProtocolFeeControllerTest is IProtocolFeeController {
10
    using PoolIdLibrary for PoolKey;
11

                            
                        
12
    mapping(PoolId => uint24) public protocolFee;
13

                            
                        
14
√ 1
⟳ 1
    function protocolFeeForPool(PoolKey memory key) external view returns (uint24) {
15
√ 2
⟳ 2
        return protocolFee[key.toId()];
16
    }
17

                            
                        
18
    // for tests to set pool protocol fees
19
    function setProtocolFeeForPool(PoolId id, uint24 fee) external {
20
        protocolFee[id] = fee;
21
    }
22
}
23

                            
                        
24
/// @notice Reverts on call
25
√ 17
contract RevertingProtocolFeeControllerTest is IProtocolFeeController {
26
    function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) {
27
        revert();
28
    }
29
}
30

                            
                        
31
/// @notice Returns an out of bounds protocol fee
32
√ 17
contract OutOfBoundsProtocolFeeControllerTest is IProtocolFeeController {
33
    function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) {
34
        // set both protocol fees to 1001, which is greater than MAX_PROTOCOL_FEE
35
        return (1001 << 12) | 1001;
36
    }
37
}
38

                            
                        
39
/// @notice Return a value that overflows a uint24
40
√ 17
contract OverflowProtocolFeeControllerTest is IProtocolFeeController {
41
    function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) {
42
        assembly {
43
            let ptr := mload(0x40)
44
            mstore(ptr, 0xFFFFAAA001)
45
            return(ptr, 0x20)
46
        }
47
    }
48
}
49

                            
                        
50
/// @notice Returns data that is larger than a word
51
√ 17
contract InvalidReturnSizeProtocolFeeControllerTest is IProtocolFeeController {
52
    function protocolFeeForPool(PoolKey memory /* key */ ) external pure returns (uint24) {
53
        address a = address(1);
54
        assembly {
55
            let ptr := mload(0x40)
56
            mstore(ptr, a)
57
            mstore(add(ptr, 0x20), a)
58
            return(ptr, 0x40)
59
        }
60
    }
61
}
62

                            
                        

Lines covered: 0 / 8 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {ProtocolFees} from "../ProtocolFees.sol";
5
import {IProtocolFeeController} from "../interfaces/IProtocolFeeController.sol";
6
import {PoolKey} from "../types/PoolKey.sol";
7
import {Currency} from "../types/Currency.sol";
8
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
9
import {Pool} from "../libraries/Pool.sol";
10
import {Slot0} from "../types/Slot0.sol";
11

                            
                        
12
contract ProtocolFeesImplementation is ProtocolFees {
13
    using PoolIdLibrary for PoolKey;
14

                            
                        
15
    mapping(PoolId id => Pool.State) internal _pools;
16

                            
                        
17
    constructor(uint256 _controllerGasLimit) ProtocolFees(_controllerGasLimit) {}
18

                            
                        
19
    // Used to set the price of a pool to pretend that the pool has been initialized in order to successfully set a protocol fee
20
    function setPrice(PoolKey memory key, uint160 sqrtPriceX96) public {
21
        Pool.State storage pool = _getPool(key.toId());
22
        pool.slot0 = pool.slot0.setSqrtPriceX96(sqrtPriceX96);
23
    }
24

                            
                        
25
    function _getPool(PoolId id) internal view override returns (Pool.State storage) {
26
        return _pools[id];
27
    }
28

                            
                        
29
    function fetchProtocolFee(PoolKey memory key) public returns (bool, uint24) {
30
        return ProtocolFees._fetchProtocolFee(key);
31
    }
32

                            
                        
33
    function updateProtocolFees(Currency currency, uint256 amount) public {
34
        ProtocolFees._updateProtocolFees(currency, amount);
35
    }
36
}
37

                            
                        

Lines covered: 0 / 66 (0.0%)

1
// SPDX-License-Identifier: BUSL-1.1
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Hooks} from "../libraries/Hooks.sol";
5
import {Pool} from "../libraries/Pool.sol";
6
import {SafeCast} from "../libraries/SafeCast.sol";
7
import {Position} from "../libraries/Position.sol";
8
import {LPFeeLibrary} from "../libraries/LPFeeLibrary.sol";
9
import {Currency, CurrencyLibrary} from "../types/Currency.sol";
10
import {PoolKey} from "../types/PoolKey.sol";
11
import {TickMath} from "../libraries/TickMath.sol";
12
import {NoDelegateCall} from "../NoDelegateCall.sol";
13
import {IHooks} from "../interfaces/IHooks.sol";
14
import {IPoolManager} from "../interfaces/IPoolManager.sol";
15
import {IUnlockCallback} from "../interfaces/callback/IUnlockCallback.sol";
16
import {ProtocolFees} from "../ProtocolFees.sol";
17
import {ERC6909Claims} from "../ERC6909Claims.sol";
18
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
19
import {BalanceDelta, BalanceDeltaLibrary, toBalanceDelta} from "../types/BalanceDelta.sol";
20
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
21
import {Lock} from "../libraries/Lock.sol";
22
import {CurrencyDelta} from "../libraries/CurrencyDelta.sol";
23
import {NonZeroDeltaCount} from "../libraries/NonZeroDeltaCount.sol";
24
import {CurrencyReserves} from "../libraries/CurrencyReserves.sol";
25
import {Extsload} from "../Extsload.sol";
26
import {Exttload} from "../Exttload.sol";
27
import {CustomRevert} from "../libraries/CustomRevert.sol";
28

                            
                        
29
/// @notice A proxy pool manager that delegates calls to the real/delegate pool manager
30
contract ProxyPoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims, Extsload, Exttload {
31
    using PoolIdLibrary for PoolKey;
32
    using SafeCast for *;
33
    using Pool for *;
34
    using Hooks for IHooks;
35
    using Position for mapping(bytes32 => Position.Info);
36
    using CurrencyDelta for Currency;
37
    using LPFeeLibrary for uint24;
38
    using CurrencyReserves for Currency;
39
    using CustomRevert for bytes4;
40

                            
                        
41
    /// @inheritdoc IPoolManager
42
    int24 public constant MAX_TICK_SPACING = TickMath.MAX_TICK_SPACING;
43

                            
                        
44
    /// @inheritdoc IPoolManager
45
    int24 public constant MIN_TICK_SPACING = TickMath.MIN_TICK_SPACING;
46

                            
                        
47
    mapping(PoolId id => Pool.State) internal _pools;
48

                            
                        
49
    address internal immutable _delegateManager;
50

                            
                        
51
    constructor(address delegateManager, uint256 controllerGasLimit) ProtocolFees(controllerGasLimit) {
52
        _delegateManager = delegateManager;
53
    }
54

                            
                        
55
    /// @notice This will revert if the contract is locked
56
    modifier onlyWhenUnlocked() {
57
        if (!Lock.isUnlocked()) ManagerLocked.selector.revertWith();
58
        _;
59
    }
60

                            
                        
61
    /// @inheritdoc IPoolManager
62
    function unlock(bytes calldata data) external noDelegateCall returns (bytes memory result) {
63
        if (Lock.isUnlocked()) AlreadyUnlocked.selector.revertWith();
64

                            
                        
65
        Lock.unlock();
66

                            
                        
67
        // the caller does everything in this callback, including paying what they owe via calls to settle
68
        result = IUnlockCallback(msg.sender).unlockCallback(data);
69

                            
                        
70
        if (NonZeroDeltaCount.read() != 0) CurrencyNotSettled.selector.revertWith();
71
        Lock.lock();
72
    }
73

                            
                        
74
    /// @inheritdoc IPoolManager
75
    function initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData)
76
        external
77
        noDelegateCall
78
        returns (int24 tick)
79
    {
80
        // see TickBitmap.sol for overflow conditions that can arise from tick spacing being too large
81
        if (key.tickSpacing > MAX_TICK_SPACING) TickSpacingTooLarge.selector.revertWith(key.tickSpacing);
82
        if (key.tickSpacing < MIN_TICK_SPACING) TickSpacingTooSmall.selector.revertWith(key.tickSpacing);
83
        if (key.currency0 >= key.currency1) {
84
            CurrenciesOutOfOrderOrEqual.selector.revertWith(
85
                Currency.unwrap(key.currency0), Currency.unwrap(key.currency1)
86
            );
87
        }
88
        if (!key.hooks.isValidHookAddress(key.fee)) Hooks.HookAddressNotValid.selector.revertWith(address(key.hooks));
89

                            
                        
90
        uint24 lpFee = key.fee.getInitialLPFee();
91

                            
                        
92
        key.hooks.beforeInitialize(key, sqrtPriceX96, hookData);
93

                            
                        
94
        PoolId id = key.toId();
95
        (, uint24 protocolFee) = _fetchProtocolFee(key);
96

                            
                        
97
        tick = _pools[id].initialize(sqrtPriceX96, protocolFee, lpFee);
98

                            
                        
99
        key.hooks.afterInitialize(key, sqrtPriceX96, tick, hookData);
100

                            
                        
101
        // emit all details of a pool key. poolkeys are not saved in storage and must always be provided by the caller
102
        // the key's fee may be a static fee or a sentinel to denote a dynamic fee.
103
        emit Initialize(id, key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks);
104
    }
105

                            
                        
106
    /// @inheritdoc IPoolManager
107
    function modifyLiquidity(
108
        PoolKey memory key,
109
        IPoolManager.ModifyLiquidityParams memory params,
110
        bytes calldata hookData
111
    ) external onlyWhenUnlocked noDelegateCall returns (BalanceDelta callerDelta, BalanceDelta feesAccrued) {
112
        bytes memory result = _delegateCall(
113
            _delegateManager, abi.encodeWithSelector(this.modifyLiquidity.selector, key, params, hookData)
114
        );
115

                            
                        
116
        return abi.decode(result, (BalanceDelta, BalanceDelta));
117
    }
118

                            
                        
119
    /// @inheritdoc IPoolManager
120
    function swap(PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData)
121
        external
122
        onlyWhenUnlocked
123
        noDelegateCall
124
        returns (BalanceDelta swapDelta)
125
    {
126
        bytes memory result =
127
            _delegateCall(_delegateManager, abi.encodeWithSelector(this.swap.selector, key, params, hookData));
128

                            
                        
129
        return abi.decode(result, (BalanceDelta));
130
    }
131

                            
                        
132
    /// @inheritdoc IPoolManager
133
    function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData)
134
        external
135
        onlyWhenUnlocked
136
        noDelegateCall
137
        returns (BalanceDelta delta)
138
    {
139
        bytes memory result = _delegateCall(
140
            _delegateManager, abi.encodeWithSelector(this.donate.selector, key, amount0, amount1, hookData)
141
        );
142

                            
                        
143
        return abi.decode(result, (BalanceDelta));
144
    }
145

                            
                        
146
    /// @inheritdoc IPoolManager
147
    function sync(Currency currency) public {
148
        CurrencyReserves.requireNotSynced();
149
        if (currency.isNative()) return;
150
        uint256 balance = currency.balanceOfSelf();
151
        CurrencyReserves.syncCurrencyAndReserves(currency, balance);
152
    }
153

                            
                        
154
    /// @inheritdoc IPoolManager
155
    function take(Currency currency, address to, uint256 amount) external onlyWhenUnlocked noDelegateCall {
156
        _delegateCall(_delegateManager, abi.encodeWithSelector(this.take.selector, currency, to, amount));
157
    }
158

                            
                        
159
    /// @inheritdoc IPoolManager
160
    function settle() external payable onlyWhenUnlocked noDelegateCall returns (uint256 paid) {
161
        bytes memory result = _delegateCall(_delegateManager, abi.encodeWithSelector(this.settle.selector));
162

                            
                        
163
        return abi.decode(result, (uint256));
164
    }
165

                            
                        
166
    /// @inheritdoc IPoolManager
167
    function settleFor(address recipient) external payable onlyWhenUnlocked noDelegateCall returns (uint256 paid) {
168
        bytes memory result =
169
            _delegateCall(_delegateManager, abi.encodeWithSelector(this.settleFor.selector, recipient));
170

                            
                        
171
        return abi.decode(result, (uint256));
172
    }
173

                            
                        
174
    /// @inheritdoc IPoolManager
175
    function clear(Currency currency, uint256 amount) external onlyWhenUnlocked {
176
        _delegateCall(_delegateManager, abi.encodeWithSelector(this.clear.selector, currency, amount));
177
    }
178

                            
                        
179
    /// @inheritdoc IPoolManager
180
    function mint(address to, uint256 id, uint256 amount) external onlyWhenUnlocked noDelegateCall {
181
        _delegateCall(_delegateManager, abi.encodeWithSelector(this.mint.selector, to, id, amount));
182
    }
183

                            
                        
184
    /// @inheritdoc IPoolManager
185
    function burn(address from, uint256 id, uint256 amount) external onlyWhenUnlocked noDelegateCall {
186
        _delegateCall(_delegateManager, abi.encodeWithSelector(this.burn.selector, from, id, amount));
187
    }
188

                            
                        
189
    /// @inheritdoc IPoolManager
190
    function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external {
191
        if (!key.fee.isDynamicFee() || msg.sender != address(key.hooks)) {
192
            UnauthorizedDynamicLPFeeUpdate.selector.revertWith();
193
        }
194
        newDynamicLPFee.validate();
195
        PoolId id = key.toId();
196
        _pools[id].setLPFee(newDynamicLPFee);
197
    }
198

                            
                        
199
    /// @notice Make a delegate call, bubble up any error or return the result
200
    function _delegateCall(address target, bytes memory data) internal returns (bytes memory result) {
201
        (bool success, bytes memory returnData) = target.delegatecall(data);
202

                            
                        
203
        if (!success) {
204
            if (returnData.length == 0) {
205
                revert();
206
            } else {
207
                assembly {
208
                    let size := mload(returnData)
209
                    revert(add(32, returnData), size)
210
                }
211
            }
212
        }
213

                            
                        
214
        return returnData;
215
    }
216

                            
                        
217
    /// @notice Implementation of the _getPool function defined in ProtocolFees
218
    function _getPool(PoolId id) internal view override returns (Pool.State storage) {
219
        return _pools[id];
220
    }
221
}
222

                            
                        

Lines covered: 0 / 77 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Hooks} from "../libraries/Hooks.sol";
5
import {BaseTestHooks} from "./BaseTestHooks.sol";
6
import {IHooks} from "../interfaces/IHooks.sol";
7
import {IPoolManager} from "../interfaces/IPoolManager.sol";
8
import {PoolKey} from "../types/PoolKey.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
10
import {PoolId, PoolIdLibrary} from "../types/PoolId.sol";
11
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
12
import {Currency} from "../types/Currency.sol";
13
import {PoolTestBase} from "./PoolTestBase.sol";
14
import {Constants} from "../../test/utils/Constants.sol";
15
import {Test} from "forge-std/Test.sol";
16
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
17
import {StateLibrary} from "../libraries/StateLibrary.sol";
18
import {TransientStateLibrary} from "../libraries/TransientStateLibrary.sol";
19
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
20

                            
                        
21
contract SkipCallsTestHook is BaseTestHooks, Test {
22
    using CurrencySettler for Currency;
23
    using PoolIdLibrary for PoolKey;
24
    using Hooks for IHooks;
25
    using StateLibrary for IPoolManager;
26
    using TransientStateLibrary for IPoolManager;
27

                            
                        
28
    uint256 public counter;
29
    IPoolManager manager;
30

                            
                        
31
    function setManager(IPoolManager _manager) external {
32
        manager = _manager;
33
    }
34

                            
                        
35
    function beforeInitialize(address, PoolKey calldata key, uint160 sqrtPriceX96, bytes calldata hookData)
36
        external
37
        override
38
        returns (bytes4)
39
    {
40
        counter++;
41
        _initialize(key, sqrtPriceX96, hookData);
42
        return IHooks.beforeInitialize.selector;
43
    }
44

                            
                        
45
    function afterInitialize(address, PoolKey calldata key, uint160 sqrtPriceX96, int24, bytes calldata hookData)
46
        external
47
        override
48
        returns (bytes4)
49
    {
50
        counter++;
51
        _initialize(key, sqrtPriceX96, hookData);
52
        return IHooks.afterInitialize.selector;
53
    }
54

                            
                        
55
    function beforeAddLiquidity(
56
        address,
57
        PoolKey calldata key,
58
        IPoolManager.ModifyLiquidityParams calldata params,
59
        bytes calldata hookData
60
    ) external override returns (bytes4) {
61
        counter++;
62
        _addLiquidity(key, params, hookData);
63
        return IHooks.beforeAddLiquidity.selector;
64
    }
65

                            
                        
66
    function afterAddLiquidity(
67
        address,
68
        PoolKey calldata key,
69
        IPoolManager.ModifyLiquidityParams calldata params,
70
        BalanceDelta,
71
        bytes calldata hookData
72
    ) external override returns (bytes4, BalanceDelta) {
73
        counter++;
74
        _addLiquidity(key, params, hookData);
75
        return (IHooks.afterAddLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA);
76
    }
77

                            
                        
78
    function beforeRemoveLiquidity(
79
        address,
80
        PoolKey calldata key,
81
        IPoolManager.ModifyLiquidityParams calldata params,
82
        bytes calldata hookData
83
    ) external override returns (bytes4) {
84
        counter++;
85
        _removeLiquidity(key, params, hookData);
86
        return IHooks.beforeRemoveLiquidity.selector;
87
    }
88

                            
                        
89
    function afterRemoveLiquidity(
90
        address,
91
        PoolKey calldata key,
92
        IPoolManager.ModifyLiquidityParams calldata params,
93
        BalanceDelta,
94
        bytes calldata hookData
95
    ) external override returns (bytes4, BalanceDelta) {
96
        counter++;
97
        _removeLiquidity(key, params, hookData);
98
        return (IHooks.afterRemoveLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA);
99
    }
100

                            
                        
101
    function beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata hookData)
102
        external
103
        override
104
        returns (bytes4, BeforeSwapDelta, uint24)
105
    {
106
        counter++;
107
        _swap(key, params, hookData);
108
        return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
109
    }
110

                            
                        
111
    function afterSwap(
112
        address,
113
        PoolKey calldata key,
114
        IPoolManager.SwapParams calldata params,
115
        BalanceDelta,
116
        bytes calldata hookData
117
    ) external override returns (bytes4, int128) {
118
        counter++;
119
        _swap(key, params, hookData);
120
        return (IHooks.afterSwap.selector, 0);
121
    }
122

                            
                        
123
    function beforeDonate(address, PoolKey calldata key, uint256 amt0, uint256 amt1, bytes calldata hookData)
124
        external
125
        override
126
        returns (bytes4)
127
    {
128
        counter++;
129
        _donate(key, amt0, amt1, hookData);
130
        return IHooks.beforeDonate.selector;
131
    }
132

                            
                        
133
    function afterDonate(address, PoolKey calldata key, uint256 amt0, uint256 amt1, bytes calldata hookData)
134
        external
135
        override
136
        returns (bytes4)
137
    {
138
        counter++;
139
        _donate(key, amt0, amt1, hookData);
140
        return IHooks.afterDonate.selector;
141
    }
142

                            
                        
143
    function _initialize(PoolKey memory key, uint160 sqrtPriceX96, bytes calldata hookData) public {
144
        // initialize a new pool with different fee
145
        key.fee = 2000;
146
        IPoolManager(manager).initialize(key, sqrtPriceX96, hookData);
147
    }
148

                            
                        
149
    function _swap(PoolKey calldata key, IPoolManager.SwapParams memory params, bytes calldata hookData) public {
150
        IPoolManager(manager).swap(key, params, hookData);
151
        address payer = abi.decode(hookData, (address));
152
        int256 delta0 = IPoolManager(manager).currencyDelta(address(this), key.currency0);
153
        assertEq(delta0, params.amountSpecified);
154
        int256 delta1 = IPoolManager(manager).currencyDelta(address(this), key.currency1);
155
        assert(delta1 > 0);
156
        key.currency0.settle(manager, payer, uint256(-delta0), false);
157
        key.currency1.take(manager, payer, uint256(delta1), false);
158
    }
159

                            
                        
160
    function _addLiquidity(
161
        PoolKey calldata key,
162
        IPoolManager.ModifyLiquidityParams memory params,
163
        bytes calldata hookData
164
    ) public {
165
        IPoolManager(manager).modifyLiquidity(key, params, hookData);
166
        address payer = abi.decode(hookData, (address));
167
        int256 delta0 = IPoolManager(manager).currencyDelta(address(this), key.currency0);
168
        int256 delta1 = IPoolManager(manager).currencyDelta(address(this), key.currency1);
169

                            
                        
170
        assert(delta0 < 0 || delta1 < 0);
171
        assert(!(delta0 > 0 || delta1 > 0));
172

                            
                        
173
        key.currency0.settle(manager, payer, uint256(-delta0), false);
174
        key.currency1.settle(manager, payer, uint256(-delta1), false);
175
    }
176

                            
                        
177
    function _removeLiquidity(
178
        PoolKey calldata key,
179
        IPoolManager.ModifyLiquidityParams memory params,
180
        bytes calldata hookData
181
    ) public {
182
        // first hook needs to add liquidity for itself
183
        IPoolManager.ModifyLiquidityParams memory newParams =
184
            IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: 0});
185
        IPoolManager(manager).modifyLiquidity(key, newParams, hookData);
186
        // hook removes liquidity
187
        IPoolManager(manager).modifyLiquidity(key, params, hookData);
188
        address payer = abi.decode(hookData, (address));
189
        int256 delta0 = IPoolManager(manager).currencyDelta(address(this), key.currency0);
190
        int256 delta1 = IPoolManager(manager).currencyDelta(address(this), key.currency1);
191

                            
                        
192
        assert(delta0 < 0 || delta1 < 0);
193
        assert(!(delta0 > 0 || delta1 > 0));
194

                            
                        
195
        key.currency0.settle(manager, payer, uint256(-delta0), false);
196
        key.currency1.settle(manager, payer, uint256(-delta1), false);
197
    }
198

                            
                        
199
    function _donate(PoolKey calldata key, uint256 amt0, uint256 amt1, bytes calldata hookData) public {
200
        IPoolManager(manager).donate(key, amt0, amt1, hookData);
201
        address payer = abi.decode(hookData, (address));
202
        int256 delta0 = IPoolManager(manager).currencyDelta(address(this), key.currency0);
203
        int256 delta1 = IPoolManager(manager).currencyDelta(address(this), key.currency1);
204
        key.currency0.settle(manager, payer, uint256(-delta0), false);
205
        key.currency1.settle(manager, payer, uint256(-delta1), false);
206
    }
207
}
208

                            
                        

Lines covered: 0 / 84 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {FullMath} from "../libraries/FullMath.sol";
5
import {SqrtPriceMath} from "../libraries/SqrtPriceMath.sol";
6
import {FixedPoint96} from "../libraries/FixedPoint96.sol";
7

                            
                        
8
contract SqrtPriceMathEchidnaTest {
9
    function mulDivRoundingUpInvariants(uint256 x, uint256 y, uint256 z) external pure {
10
        unchecked {
11
            require(z > 0);
12
            uint256 notRoundedUp = FullMath.mulDiv(x, y, z);
13
            uint256 roundedUp = FullMath.mulDivRoundingUp(x, y, z);
14
            assert(roundedUp >= notRoundedUp);
15
            assert(roundedUp - notRoundedUp < 2);
16
            if (roundedUp - notRoundedUp == 1) {
17
                assert(mulmod(x, y, z) > 0);
18
            } else {
19
                assert(mulmod(x, y, z) == 0);
20
            }
21
        }
22
    }
23

                            
                        
24
    function getNextSqrtPriceFromInputInvariants(uint160 sqrtP, uint128 liquidity, uint256 amountIn, bool zeroForOne)
25
        external
26
        pure
27
    {
28
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, liquidity, amountIn, zeroForOne);
29

                            
                        
30
        if (zeroForOne) {
31
            assert(sqrtQ <= sqrtP);
32
            assert(amountIn >= SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, true));
33
        } else {
34
            assert(sqrtQ >= sqrtP);
35
            assert(amountIn >= SqrtPriceMath.getAmount1Delta(sqrtP, sqrtQ, liquidity, true));
36
        }
37
    }
38

                            
                        
39
    function getNextSqrtPriceFromOutputInvariants(uint160 sqrtP, uint128 liquidity, uint256 amountOut, bool zeroForOne)
40
        external
41
        pure
42
    {
43
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, liquidity, amountOut, zeroForOne);
44

                            
                        
45
        if (zeroForOne) {
46
            assert(sqrtQ <= sqrtP);
47
            assert(amountOut <= SqrtPriceMath.getAmount1Delta(sqrtQ, sqrtP, liquidity, false));
48
        } else {
49
            assert(sqrtQ > 0); // this has to be true, otherwise we need another require
50
            assert(sqrtQ >= sqrtP);
51
            assert(amountOut <= SqrtPriceMath.getAmount0Delta(sqrtP, sqrtQ, liquidity, false));
52
        }
53
    }
54

                            
                        
55
    function getNextSqrtPriceFromAmount0RoundingUpInvariants(
56
        uint160 sqrtPX96,
57
        uint128 liquidity,
58
        uint256 amount,
59
        bool add
60
    ) external pure {
61
        require(sqrtPX96 > 0);
62
        require(liquidity > 0);
63
        uint160 sqrtQX96 = SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amount, add);
64

                            
                        
65
        if (add) {
66
            assert(sqrtQX96 <= sqrtPX96);
67
        } else {
68
            assert(sqrtQX96 >= sqrtPX96);
69
        }
70

                            
                        
71
        if (amount == 0) {
72
            assert(sqrtPX96 == sqrtQX96);
73
        }
74
    }
75

                            
                        
76
    function getNextSqrtPriceFromAmount1RoundingDownInvariants(
77
        uint160 sqrtPX96,
78
        uint128 liquidity,
79
        uint256 amount,
80
        bool add
81
    ) external pure {
82
        require(sqrtPX96 > 0);
83
        require(liquidity > 0);
84
        uint160 sqrtQX96 = SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amount, add);
85

                            
                        
86
        if (add) {
87
            assert(sqrtQX96 >= sqrtPX96);
88
        } else {
89
            assert(sqrtQX96 <= sqrtPX96);
90
        }
91

                            
                        
92
        if (amount == 0) {
93
            assert(sqrtPX96 == sqrtQX96);
94
        }
95
    }
96

                            
                        
97
    function getAmount0DeltaInvariants(uint160 sqrtP, uint160 sqrtQ, uint128 liquidity) external pure {
98
        require(sqrtP > 0 && sqrtQ > 0);
99

                            
                        
100
        uint256 amount0Down = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, false);
101
        assert(amount0Down == SqrtPriceMath.getAmount0Delta(sqrtP, sqrtQ, liquidity, false));
102

                            
                        
103
        uint256 amount0Up = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, true);
104
        assert(amount0Up == SqrtPriceMath.getAmount0Delta(sqrtP, sqrtQ, liquidity, true));
105

                            
                        
106
        assert(amount0Down <= amount0Up);
107
        // diff is 0 or 1
108
        assert(amount0Up - amount0Down < 2);
109
    }
110

                            
                        
111
    // ensure that chained division is always equal to the full-precision case for
112
    // liquidity * (sqrt(P) - sqrt(Q)) / (sqrt(P) * sqrt(Q))
113
    function getAmount0DeltaEquivalency(uint160 sqrtP, uint160 sqrtQ, uint128 liquidity, bool roundUp) external pure {
114
        require(sqrtP >= sqrtQ);
115
        require(sqrtP > 0 && sqrtQ > 0);
116
        require((sqrtP * sqrtQ) / sqrtP == sqrtQ);
117

                            
                        
118
        uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION;
119
        uint256 numerator2 = sqrtP - sqrtQ;
120
        uint256 denominator = uint256(sqrtP) * sqrtQ;
121

                            
                        
122
        uint256 safeResult = roundUp
123
            ? FullMath.mulDivRoundingUp(numerator1, numerator2, denominator)
124
            : FullMath.mulDiv(numerator1, numerator2, denominator);
125
        uint256 fullResult = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, roundUp);
126

                            
                        
127
        assert(safeResult == fullResult);
128
    }
129

                            
                        
130
    function getAmount1DeltaInvariants(uint160 sqrtP, uint160 sqrtQ, uint128 liquidity) external pure {
131
        require(sqrtP > 0 && sqrtQ > 0);
132

                            
                        
133
        uint256 amount1Down = SqrtPriceMath.getAmount1Delta(sqrtP, sqrtQ, liquidity, false);
134
        assert(amount1Down == SqrtPriceMath.getAmount1Delta(sqrtQ, sqrtP, liquidity, false));
135

                            
                        
136
        uint256 amount1Up = SqrtPriceMath.getAmount1Delta(sqrtP, sqrtQ, liquidity, true);
137
        assert(amount1Up == SqrtPriceMath.getAmount1Delta(sqrtQ, sqrtP, liquidity, true));
138

                            
                        
139
        assert(amount1Down <= amount1Up);
140
        // diff is 0 or 1
141
        assert(amount1Up - amount1Down < 2);
142
    }
143

                            
                        
144
    function getAmount0DeltaSignedInvariants(uint160 sqrtP, uint160 sqrtQ, int128 liquidity) external pure {
145
        require(sqrtP > 0 && sqrtQ > 0);
146

                            
                        
147
        int256 amount0 = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity);
148
        if (liquidity < 0) assert(amount0 <= 0);
149
        if (liquidity > 0) {
150
            if (sqrtP == sqrtQ) assert(amount0 == 0);
151
            else assert(amount0 > 0);
152
        }
153
        if (liquidity == 0) assert(amount0 == 0);
154
    }
155

                            
                        
156
    function getAmount1DeltaSignedInvariants(uint160 sqrtP, uint160 sqrtQ, int128 liquidity) external pure {
157
        require(sqrtP > 0 && sqrtQ > 0);
158

                            
                        
159
        int256 amount1 = SqrtPriceMath.getAmount1Delta(sqrtP, sqrtQ, liquidity);
160
        if (liquidity < 0) assert(amount1 <= 0);
161
        if (liquidity > 0) {
162
            if (sqrtP == sqrtQ) assert(amount1 == 0);
163
            else assert(amount1 > 0);
164
        }
165
        if (liquidity == 0) assert(amount1 == 0);
166
    }
167

                            
                        
168
    function getOutOfRangeMintInvariants(uint160 sqrtA, uint160 sqrtB, int128 liquidity) external pure {
169
        require(sqrtA > 0 && sqrtB > 0);
170
        require(liquidity > 0);
171

                            
                        
172
        int256 amount0 = SqrtPriceMath.getAmount0Delta(sqrtA, sqrtB, liquidity);
173
        int256 amount1 = SqrtPriceMath.getAmount1Delta(sqrtA, sqrtB, liquidity);
174

                            
                        
175
        if (sqrtA == sqrtB) {
176
            assert(amount0 == 0);
177
            assert(amount1 == 0);
178
        } else {
179
            assert(amount0 > 0);
180
            assert(amount1 > 0);
181
        }
182
    }
183

                            
                        
184
    function getInRangeMintInvariants(uint160 sqrtLower, uint160 sqrtCurrent, uint160 sqrtUpper, int128 liquidity)
185
        external
186
        pure
187
    {
188
        require(sqrtLower > 0);
189
        require(sqrtLower < sqrtUpper);
190
        require(sqrtLower <= sqrtCurrent && sqrtCurrent <= sqrtUpper);
191
        require(liquidity > 0);
192

                            
                        
193
        int256 amount0 = SqrtPriceMath.getAmount0Delta(sqrtCurrent, sqrtUpper, liquidity);
194
        int256 amount1 = SqrtPriceMath.getAmount1Delta(sqrtLower, sqrtCurrent, liquidity);
195

                            
                        
196
        assert(amount0 > 0 || amount1 > 0);
197
    }
198
}
199

                            
                        

Lines covered: 1 / 12 (8.3%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Currency} from "../types/Currency.sol";
5
import {IPoolManager} from "../interfaces/IPoolManager.sol";
6
import {BalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
7
import {PoolKey} from "../types/PoolKey.sol";
8
import {IHooks} from "../interfaces/IHooks.sol";
9
import {Hooks} from "../libraries/Hooks.sol";
10
import {PoolTestBase} from "./PoolTestBase.sol";
11
import {CurrencySettler} from "../../test/utils/CurrencySettler.sol";
12

                            
                        
13
contract SwapRouterNoChecks is PoolTestBase {
14
    using CurrencySettler for Currency;
15
    using Hooks for IHooks;
16

                            
                        
17
√ 27
    constructor(IPoolManager _manager) PoolTestBase(_manager) {}
18

                            
                        
19
    error NoSwapOccurred();
20

                            
                        
21
    struct CallbackData {
22
        address sender;
23
        PoolKey key;
24
        IPoolManager.SwapParams params;
25
    }
26

                            
                        
27
    function swap(PoolKey memory key, IPoolManager.SwapParams memory params) external payable {
28
        manager.unlock(abi.encode(CallbackData(msg.sender, key, params)));
29
    }
30

                            
                        
31
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
32
        require(msg.sender == address(manager));
33

                            
                        
34
        CallbackData memory data = abi.decode(rawData, (CallbackData));
35

                            
                        
36
        BalanceDelta delta = manager.swap(data.key, data.params, new bytes(0));
37

                            
                        
38
        if (data.params.zeroForOne) {
39
            data.key.currency0.settle(manager, data.sender, uint256(int256(-delta.amount0())), false);
40
            data.key.currency1.take(manager, data.sender, uint256(int256(delta.amount1())), false);
41
        } else {
42
            data.key.currency1.settle(manager, data.sender, uint256(int256(-delta.amount1())), false);
43
            data.key.currency0.take(manager, data.sender, uint256(int256(delta.amount0())), false);
44
        }
45

                            
                        
46
        return "";
47
    }
48
}
49

                            
                        

Lines covered: 0 / 31 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
5

                            
                        
6
contract TestERC20 is IERC20Minimal {
7
    mapping(address => uint256) public override balanceOf;
8
    mapping(address => mapping(address => uint256)) public override allowance;
9

                            
                        
10
    constructor(uint256 amountToMint) {
11
        mint(msg.sender, amountToMint);
12
    }
13

                            
                        
14
    function mint(address to, uint256 amount) public {
15
        uint256 balanceNext = balanceOf[to] + amount;
16
        require(balanceNext >= amount, "overflow balance");
17
        balanceOf[to] = balanceNext;
18
    }
19

                            
                        
20
    function transfer(address recipient, uint256 amount) external override returns (bool) {
21
        uint256 balanceBefore = balanceOf[msg.sender];
22
        require(balanceBefore >= amount, "insufficient balance");
23
        balanceOf[msg.sender] = balanceBefore - amount;
24

                            
                        
25
        uint256 balanceRecipient = balanceOf[recipient];
26
        require(balanceRecipient + amount >= balanceRecipient, "recipient balance overflow");
27
        balanceOf[recipient] = balanceRecipient + amount;
28

                            
                        
29
        emit Transfer(msg.sender, recipient, amount);
30
        return true;
31
    }
32

                            
                        
33
    function approve(address spender, uint256 amount) external override returns (bool) {
34
        allowance[msg.sender][spender] = amount;
35
        emit Approval(msg.sender, spender, amount);
36
        return true;
37
    }
38

                            
                        
39
    function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
40
        uint256 allowanceBefore = allowance[sender][msg.sender];
41
        require(allowanceBefore >= amount, "allowance insufficient");
42

                            
                        
43
        allowance[sender][msg.sender] = allowanceBefore - amount;
44

                            
                        
45
        uint256 balanceRecipient = balanceOf[recipient];
46
        require(balanceRecipient + amount >= balanceRecipient, "overflow balance recipient");
47
        balanceOf[recipient] = balanceRecipient + amount;
48
        uint256 balanceSender = balanceOf[sender];
49
        require(balanceSender >= amount, "underflow balance sender");
50
        balanceOf[sender] = balanceSender - amount;
51

                            
                        
52
        emit Transfer(sender, recipient, amount);
53
        return true;
54
    }
55
}
56

                            
                        

Lines covered: 0 / 31 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
5

                            
                        
6
// Regular ERC20 but it doesn't return true on transfer.
7
contract TestInvalidERC20 is IERC20Minimal {
8
    mapping(address => uint256) public override balanceOf;
9
    mapping(address => mapping(address => uint256)) public override allowance;
10

                            
                        
11
    constructor(uint256 amountToMint) {
12
        mint(msg.sender, amountToMint);
13
    }
14

                            
                        
15
    function mint(address to, uint256 amount) public {
16
        uint256 balanceNext = balanceOf[to] + amount;
17
        require(balanceNext >= amount, "overflow balance");
18
        balanceOf[to] = balanceNext;
19
    }
20

                            
                        
21
    function transfer(address recipient, uint256 amount) external override returns (bool) {
22
        uint256 balanceBefore = balanceOf[msg.sender];
23
        require(balanceBefore >= amount, "insufficient balance");
24
        balanceOf[msg.sender] = balanceBefore - amount;
25

                            
                        
26
        uint256 balanceRecipient = balanceOf[recipient];
27
        require(balanceRecipient + amount >= balanceRecipient, "recipient balance overflow");
28
        balanceOf[recipient] = balanceRecipient + amount;
29

                            
                        
30
        emit Transfer(msg.sender, recipient, amount);
31
        return false; // returns false even though it succeeded
32
    }
33

                            
                        
34
    function approve(address spender, uint256 amount) external override returns (bool) {
35
        allowance[msg.sender][spender] = amount;
36
        emit Approval(msg.sender, spender, amount);
37
        return false;
38
    }
39

                            
                        
40
    function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
41
        uint256 allowanceBefore = allowance[sender][msg.sender];
42
        require(allowanceBefore >= amount, "allowance insufficient");
43

                            
                        
44
        allowance[sender][msg.sender] = allowanceBefore - amount;
45

                            
                        
46
        uint256 balanceRecipient = balanceOf[recipient];
47
        require(balanceRecipient + amount >= balanceRecipient, "overflow balance recipient");
48
        balanceOf[recipient] = balanceRecipient + amount;
49
        uint256 balanceSender = balanceOf[sender];
50
        require(balanceSender >= amount, "underflow balance sender");
51
        balanceOf[sender] = balanceSender - amount;
52

                            
                        
53
        emit Transfer(sender, recipient, amount);
54
        return false; // returns false even though it succeeded
55
    }
56
}
57

                            
                        

Lines covered: 0 / 9 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {TickMath} from "../libraries/TickMath.sol";
5

                            
                        
6
contract TickMathEchidnaTest {
7
    // uniqueness and increasing order
8
    function checkGetSqrtPriceAtTickInvariants(int24 tick) external pure {
9
        uint160 price = TickMath.getSqrtPriceAtTick(tick);
10
        assert(TickMath.getSqrtPriceAtTick(tick - 1) < price && price < TickMath.getSqrtPriceAtTick(tick + 1));
11
        assert(price >= TickMath.MIN_SQRT_PRICE);
12
        assert(price <= TickMath.MAX_SQRT_PRICE);
13
    }
14

                            
                        
15
    // the price is always between the returned tick and the returned tick+1
16
    function checkGetTickAtSqrtPriceInvariants(uint160 price) external pure {
17
        int24 tick = TickMath.getTickAtSqrtPrice(price);
18
        assert(price >= TickMath.getSqrtPriceAtTick(tick) && price < TickMath.getSqrtPriceAtTick(tick + 1));
19
        assert(tick >= TickMath.MIN_TICK);
20
        assert(tick < TickMath.MAX_TICK);
21
    }
22
}
23

                            
                        

Lines covered: 0 / 16 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {TickMath} from "../libraries/TickMath.sol";
5

                            
                        
6
contract TickMathTest {
7
    function getSqrtPriceAtTick(int24 tick) external pure returns (uint160) {
8
        return TickMath.getSqrtPriceAtTick(tick);
9
    }
10

                            
                        
11
    function getGasCostOfGetSqrtPriceAtTick(int24 tick) external view returns (uint256) {
12
        uint256 gasBefore = gasleft();
13
        TickMath.getSqrtPriceAtTick(tick);
14
        return gasBefore - gasleft();
15
    }
16

                            
                        
17
    function getTickAtSqrtPrice(uint160 sqrtPriceX96) external pure returns (int24) {
18
        return TickMath.getTickAtSqrtPrice(sqrtPriceX96);
19
    }
20

                            
                        
21
    function getGasCostOfGetTickAtSqrtPrice(uint160 sqrtPriceX96) external view returns (uint256) {
22
        uint256 gasBefore = gasleft();
23
        TickMath.getTickAtSqrtPrice(sqrtPriceX96);
24
        return gasBefore - gasleft();
25
    }
26

                            
                        
27
    function MIN_SQRT_PRICE() external pure returns (uint160) {
28
        return TickMath.MIN_SQRT_PRICE;
29
    }
30

                            
                        
31
    function MAX_SQRT_PRICE() external pure returns (uint160) {
32
        return TickMath.MAX_SQRT_PRICE;
33
    }
34

                            
                        
35
    function MIN_TICK() external pure returns (int24) {
36
        return TickMath.MIN_TICK;
37
    }
38

                            
                        
39
    function MAX_TICK() external pure returns (int24) {
40
        return TickMath.MAX_TICK;
41
    }
42
}
43

                            
                        

Lines covered: 0 / 44 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Pool} from "../libraries/Pool.sol";
5

                            
                        
6
contract TickOverflowSafetyEchidnaTest {
7
    using Pool for Pool.State;
8

                            
                        
9
    int24 private constant MIN_TICK = -16;
10
    int24 private constant MAX_TICK = 16;
11

                            
                        
12
    Pool.State private pool;
13
    int24 private tick = 0;
14

                            
                        
15
    // half the cap of fee growth has happened, this can overflow
16
    uint256 feeGrowthGlobal0X128 = type(uint256).max / 2;
17
    uint256 feeGrowthGlobal1X128 = type(uint256).max / 2;
18

                            
                        
19
    // used to track how much total liquidity has been added. should never be negative
20
    int256 totalLiquidity = 0;
21
    // how much total growth has happened, this cannot overflow
22
    uint256 private totalGrowth0 = 0;
23
    uint256 private totalGrowth1 = 0;
24

                            
                        
25
    function increaseFeeGrowthGlobal0X128(uint256 amount) external {
26
        require(totalGrowth0 + amount > totalGrowth0); // overflow check
27
        feeGrowthGlobal0X128 += amount; // overflow desired
28
        totalGrowth0 += amount;
29
    }
30

                            
                        
31
    function increaseFeeGrowthGlobal1X128(uint256 amount) external {
32
        require(totalGrowth1 + amount > totalGrowth1); // overflow check
33
        feeGrowthGlobal1X128 += amount; // overflow desired
34
        totalGrowth1 += amount;
35
    }
36

                            
                        
37
    function setPosition(int24 tickLower, int24 tickUpper, int128 liquidityDelta) external {
38
        require(tickLower > MIN_TICK);
39
        require(tickUpper < MAX_TICK);
40
        require(tickLower < tickUpper);
41
        (bool flippedLower,) = pool.updateTick(tickLower, liquidityDelta, false);
42
        (bool flippedUpper,) = pool.updateTick(tickUpper, liquidityDelta, true);
43

                            
                        
44
        if (flippedLower) {
45
            if (liquidityDelta < 0) {
46
                assert(pool.ticks[tickLower].liquidityGross == 0);
47
                pool.clearTick(tickLower);
48
            } else {
49
                assert(pool.ticks[tickLower].liquidityGross > 0);
50
            }
51
        }
52

                            
                        
53
        if (flippedUpper) {
54
            if (liquidityDelta < 0) {
55
                assert(pool.ticks[tickUpper].liquidityGross == 0);
56
                pool.clearTick(tickUpper);
57
            } else {
58
                assert(pool.ticks[tickUpper].liquidityGross > 0);
59
            }
60
        }
61

                            
                        
62
        totalLiquidity += liquidityDelta;
63
        // requires should have prevented this
64
        assert(totalLiquidity >= 0);
65

                            
                        
66
        if (totalLiquidity == 0) {
67
            totalGrowth0 = 0;
68
            totalGrowth1 = 0;
69
        }
70
    }
71

                            
                        
72
    function moveToTick(int24 target) external {
73
        require(target > MIN_TICK);
74
        require(target < MAX_TICK);
75
        while (tick != target) {
76
            if (tick < target) {
77
                if (pool.ticks[tick + 1].liquidityGross > 0) {
78
                    pool.crossTick(tick + 1, feeGrowthGlobal0X128, feeGrowthGlobal1X128);
79
                }
80
                tick++;
81
            } else {
82
                if (pool.ticks[tick].liquidityGross > 0) {
83
                    pool.crossTick(tick, feeGrowthGlobal0X128, feeGrowthGlobal1X128);
84
                }
85
                tick--;
86
            }
87
        }
88
    }
89
}
90

                            
                        

Lines covered: 12 / 23 (52.2%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {SafeCast} from "../libraries/SafeCast.sol";
5

                            
                        
6
/// @dev Two `int128` values packed into a single `int256` where the upper 128 bits represent the amount0
7
/// and the lower 128 bits represent the amount1.
8
type BalanceDelta is int256;
9

                            
                        
10
using {add as +, sub as -, eq as ==, neq as !=} for BalanceDelta global;
11
using BalanceDeltaLibrary for BalanceDelta global;
12
using SafeCast for int256;
13

                            
                        
14
function toBalanceDelta(int128 _amount0, int128 _amount1) pure returns (BalanceDelta balanceDelta) {
15
    assembly ("memory-safe") {
16
√ 23
⟳ 23
        balanceDelta := or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1))
17
    }
18
}
19

                            
                        
20
√ 1
⟳ 1
function add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
21
    int256 res0;
22
    int256 res1;
23
    assembly ("memory-safe") {
24
√ 1
⟳ 1
        let a0 := sar(128, a)
25
√ 1
⟳ 1
        let a1 := signextend(15, a)
26
√ 3
⟳ 3
        let b0 := sar(128, b)
27
√ 3
⟳ 3
        let b1 := signextend(15, b)
28
√ 2
⟳ 2
        res0 := add(a0, b0)
29
√ 1
⟳ 1
        res1 := add(a1, b1)
30
    }
31
√ 2
⟳ 2
    return toBalanceDelta(res0.toInt128(), res1.toInt128());
32
}
33

                            
                        
34
function sub(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
35
    int256 res0;
36
    int256 res1;
37
    assembly ("memory-safe") {
38
        let a0 := sar(128, a)
39
        let a1 := signextend(15, a)
40
        let b0 := sar(128, b)
41
        let b1 := signextend(15, b)
42
        res0 := sub(a0, b0)
43
        res1 := sub(a1, b1)
44
    }
45
    return toBalanceDelta(res0.toInt128(), res1.toInt128());
46
}
47

                            
                        
48
function eq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
49
    return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b);
50
}
51

                            
                        
52
function neq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
53
√ 4
⟳ 4
    return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b);
54
}
55

                            
                        
56
/// @notice Library for getting the amount0 and amount1 deltas from the BalanceDelta type
57
library BalanceDeltaLibrary {
58
    /// @notice A BalanceDelta of 0
59
    BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0);
60

                            
                        
61
    function amount0(BalanceDelta balanceDelta) internal pure returns (int128 _amount0) {
62
        assembly ("memory-safe") {
63
√ 3
⟳ 3
            _amount0 := sar(128, balanceDelta)
64
        }
65
    }
66

                            
                        
67
    function amount1(BalanceDelta balanceDelta) internal pure returns (int128 _amount1) {
68
        assembly ("memory-safe") {
69
√ 3
⟳ 3
            _amount1 := signextend(15, balanceDelta)
70
        }
71
    }
72
}
73

                            
                        

Lines covered: 0 / 3 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
// Return type of the beforeSwap hook.
5
// Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in unspecified tokens (to match the afterSwap hook)
6
type BeforeSwapDelta is int256;
7

                            
                        
8
// Creates a BeforeSwapDelta from specified and unspecified
9
function toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified)
10
    pure
11
    returns (BeforeSwapDelta beforeSwapDelta)
12
{
13
    assembly ("memory-safe") {
14
        beforeSwapDelta := or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified))
15
    }
16
}
17

                            
                        
18
/// @notice Library for getting the specified and unspecified deltas from the BeforeSwapDelta type
19
library BeforeSwapDeltaLibrary {
20
    /// @notice A BeforeSwapDelta of 0
21
    BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0);
22

                            
                        
23
    /// extracts int128 from the upper 128 bits of the BeforeSwapDelta
24
    /// returned by beforeSwap
25
    function getSpecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaSpecified) {
26
        assembly ("memory-safe") {
27
            deltaSpecified := sar(128, delta)
28
        }
29
    }
30

                            
                        
31
    /// extracts int128 from the lower 128 bits of the BeforeSwapDelta
32
    /// returned by beforeSwap and afterSwap
33
    function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) {
34
        assembly ("memory-safe") {
35
            deltaUnspecified := signextend(15, delta)
36
        }
37
    }
38
}
39

                            
                        

Lines covered: 22 / 33 (66.7%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
5
import {CustomRevert} from "../libraries/CustomRevert.sol";
6

                            
                        
7
type Currency is address;
8

                            
                        
9
using {greaterThan as >, lessThan as <, greaterThanOrEqualTo as >=, equals as ==} for Currency global;
10
using CurrencyLibrary for Currency global;
11

                            
                        
12
function equals(Currency currency, Currency other) pure returns (bool) {
13
    return Currency.unwrap(currency) == Currency.unwrap(other);
14
}
15

                            
                        
16
function greaterThan(Currency currency, Currency other) pure returns (bool) {
17
    return Currency.unwrap(currency) > Currency.unwrap(other);
18
}
19

                            
                        
20
function lessThan(Currency currency, Currency other) pure returns (bool) {
21
    return Currency.unwrap(currency) < Currency.unwrap(other);
22
}
23

                            
                        
24
function greaterThanOrEqualTo(Currency currency, Currency other) pure returns (bool) {
25
√ 7
⟳ 7
    return Currency.unwrap(currency) >= Currency.unwrap(other);
26
}
27

                            
                        
28
/// @title CurrencyLibrary
29
/// @dev This library allows for transferring and holding native tokens and ERC20 tokens
30
library CurrencyLibrary {
31
    using CustomRevert for bytes4;
32

                            
                        
33
    /// @notice Thrown when a native transfer fails
34
    /// @param revertReason bubbled up revert reason
35
    error NativeTransferFailed(bytes revertReason);
36

                            
                        
37
    /// @notice Thrown when an ERC20 transfer fails
38
    /// @param revertReason bubbled up revert reason
39
    error ERC20TransferFailed(bytes revertReason);
40

                            
                        
41
    /// @notice A constant to represent the native currency
42
    Currency public constant NATIVE = Currency.wrap(address(0));
43

                            
                        
44
    function transfer(Currency currency, address to, uint256 amount) internal {
45
        // altered from https://github.com/transmissions11/solmate/blob/44a9963d4c78111f77caa0e65d677b8b46d6f2e6/src/utils/SafeTransferLib.sol
46
        // modified custom error selectors
47

                            
                        
48
√ 1
⟳ 1
        bool success;
49
√ 3
⟳ 3
        if (currency.isNative()) {
50
            assembly ("memory-safe") {
51
                // Transfer the ETH and revert if it fails.
52
√ 7
⟳ 7
                success := call(gas(), to, amount, 0, 0, 0, 0)
53
            }
54
            // revert with NativeTransferFailed, containing the bubbled up error as an argument
55
√ 1
⟳ 2
            if (!success) NativeTransferFailed.selector.bubbleUpAndRevertWith();
56
        } else {
57
            assembly ("memory-safe") {
58
                // Get a pointer to some free memory.
59
√ 1
⟳ 1
                let fmp := mload(0x40)
60

                            
                        
61
                // Write the abi-encoded calldata into memory, beginning with the function selector.
62
√ 2
⟳ 2
                mstore(fmp, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
63
√ 4
⟳ 4
                mstore(add(fmp, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
64
√ 3
⟳ 3
                mstore(add(fmp, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
65

                            
                        
66
                success :=
67
                    and(
68
                        // Set success to whether the call reverted, if not we check it either
69
                        // returned exactly 1 (can't just be non-zero data), or had no return data.
70
√ 5
⟳ 5
                        or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
71
                        // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
72
                        // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
73
                        // Counterintuitively, this call must be positioned second to the or() call in the
74
                        // surrounding and() call or else returndatasize() will be zero during the computation.
75
√ 7
⟳ 7
                        call(gas(), currency, 0, fmp, 68, 0, 32)
76
                    )
77

                            
                        
78
                // Now clean the memory we used
79
√ 2
⟳ 2
                mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here
80
√ 3
⟳ 3
                mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here
81
√ 3
⟳ 3
                mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here
82
            }
83
            // revert with ERC20TransferFailed, containing the bubbled up error as an argument
84
√ 1
⟳ 2
            if (!success) ERC20TransferFailed.selector.bubbleUpAndRevertWith();
85
        }
86
    }
87

                            
                        
88
√ 1
⟳ 1
    function balanceOfSelf(Currency currency) internal view returns (uint256) {
89
√ 3
⟳ 3
        if (currency.isNative()) {
90
            return address(this).balance;
91
        } else {
92
√ 7
⟳ 7
            return IERC20Minimal(Currency.unwrap(currency)).balanceOf(address(this));
93
        }
94
    }
95

                            
                        
96
    function balanceOf(Currency currency, address owner) internal view returns (uint256) {
97
        if (currency.isNative()) {
98
            return owner.balance;
99
        } else {
100
            return IERC20Minimal(Currency.unwrap(currency)).balanceOf(owner);
101
        }
102
    }
103

                            
                        
104
    function isNative(Currency currency) internal pure returns (bool) {
105
√ 4
⟳ 4
        return Currency.unwrap(currency) == Currency.unwrap(NATIVE);
106
    }
107

                            
                        
108
√ 1
⟳ 1
    function isZero(Currency currency) internal pure returns (bool) {
109
√ 1
⟳ 1
        return isNative(currency);
110
    }
111

                            
                        
112
    function toId(Currency currency) internal pure returns (uint256) {
113
√ 18
⟳ 24
        return uint160(Currency.unwrap(currency));
114
    }
115

                            
                        
116
    // If the upper 12 bytes are non-zero, they will be zero-ed out
117
    // Therefore, fromId() and toId() are not inverses of each other
118
    function fromId(uint256 id) internal pure returns (Currency) {
119
        return Currency.wrap(address(uint160(id)));
120
    }
121
}
122

                            
                        

Lines covered: 1 / 2 (50.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {PoolKey} from "./PoolKey.sol";
5

                            
                        
6
type PoolId is bytes32;
7

                            
                        
8
/// @notice Library for computing the ID of a pool
9
library PoolIdLibrary {
10
    /// @notice Returns value equal to keccak256(abi.encode(poolKey))
11
    function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) {
12
        assembly ("memory-safe") {
13
√ 6
⟳ 6
            poolId := keccak256(poolKey, mul(32, 5))
14
        }
15
    }
16
}
17

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {Currency} from "./Currency.sol";
5
import {IHooks} from "../interfaces/IHooks.sol";
6

                            
                        
7
/// @notice Returns the key for identifying a pool
8
struct PoolKey {
9
    /// @notice The lower currency of the pool, sorted numerically
10
    Currency currency0;
11
    /// @notice The higher currency of the pool, sorted numerically
12
    Currency currency1;
13
    /// @notice The pool swap fee, capped at 1_000_000. If the highest bit is 1, the pool has a dynamic fee and must be exactly equal to 0x800000
14
    uint24 fee;
15
    /// @notice Ticks that involve positions must be a multiple of tick spacing
16
    int24 tickSpacing;
17
    /// @notice The hooks of the pool
18
    IHooks hooks;
19
}
20

                            
                        

Lines covered: 8 / 12 (66.7%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
/**
5
 * @dev Slot0 is a packed version of solidity structure.
6
 * Using the packaged version saves gas by not storing the structure fields in memory slots.
7
 *
8
 * Layout:
9
 * 24 bits empty | 24 bits lpFee | 12 bits protocolFee 1->0 | 12 bits protocolFee 0->1 | 24 bits tick | 160 bits sqrtPriceX96
10
 *
11
 * Fields in the direction from the least significant bit:
12
 *
13
 * The current price
14
 * uint160 sqrtPriceX96;
15
 *
16
 * The current tick
17
 * int24 tick;
18
 *
19
 * Protocol fee, expressed in hundredths of a bip, upper 12 bits are for 1->0, and the lower 12 are for 0->1
20
 * the maximum is 1000 - meaning the maximum protocol fee is 0.1%
21
 * the protocolFee is taken from the input first, then the lpFee is taken from the remaining input
22
 * uint24 protocolFee;
23
 *
24
 * The current LP fee of the pool. If the pool is dynamic, this does not include the dynamic fee flag.
25
 * uint24 lpFee;
26
 */
27
type Slot0 is bytes32;
28

                            
                        
29
using Slot0Library for Slot0 global;
30

                            
                        
31
/// @notice Library for getting and setting values in the Slot0 type
32
library Slot0Library {
33
    uint160 internal constant MASK_160_BITS = 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
34
    uint24 internal constant MASK_24_BITS = 0xFFFFFF;
35

                            
                        
36
    uint8 internal constant TICK_OFFSET = 160;
37
    uint8 internal constant PROTOCOL_FEE_OFFSET = 184;
38
    uint8 internal constant LP_FEE_OFFSET = 208;
39

                            
                        
40
    // #### GETTERS ####
41
    function sqrtPriceX96(Slot0 _packed) internal pure returns (uint160 _sqrtPriceX96) {
42
        assembly ("memory-safe") {
43
            _sqrtPriceX96 := and(MASK_160_BITS, _packed)
44
        }
45
    }
46

                            
                        
47
    function tick(Slot0 _packed) internal pure returns (int24 _tick) {
48
        assembly ("memory-safe") {
49
√ 9
⟳ 9
            _tick := signextend(2, shr(TICK_OFFSET, _packed))
50
        }
51
    }
52

                            
                        
53
    function protocolFee(Slot0 _packed) internal pure returns (uint24 _protocolFee) {
54
        assembly ("memory-safe") {
55
√ 1
⟳ 1
            _protocolFee := and(MASK_24_BITS, shr(PROTOCOL_FEE_OFFSET, _packed))
56
        }
57
    }
58

                            
                        
59
    function lpFee(Slot0 _packed) internal pure returns (uint24 _lpFee) {
60
        assembly ("memory-safe") {
61
√ 2
⟳ 2
            _lpFee := and(MASK_24_BITS, shr(LP_FEE_OFFSET, _packed))
62
        }
63
    }
64

                            
                        
65
    // #### SETTERS ####
66
    function setSqrtPriceX96(Slot0 _packed, uint160 _sqrtPriceX96) internal pure returns (Slot0 _result) {
67
        assembly ("memory-safe") {
68
√ 3
⟳ 3
            _result := or(and(not(MASK_160_BITS), _packed), and(MASK_160_BITS, _sqrtPriceX96))
69
        }
70
    }
71

                            
                        
72
    function setTick(Slot0 _packed, int24 _tick) internal pure returns (Slot0 _result) {
73
        assembly ("memory-safe") {
74
√ 3
⟳ 3
            _result := or(and(not(shl(TICK_OFFSET, MASK_24_BITS)), _packed), shl(TICK_OFFSET, and(MASK_24_BITS, _tick)))
75
        }
76
    }
77

                            
                        
78
    function setProtocolFee(Slot0 _packed, uint24 _protocolFee) internal pure returns (Slot0 _result) {
79
        assembly ("memory-safe") {
80
            _result :=
81
                or(
82
√ 1
⟳ 1
                    and(not(shl(PROTOCOL_FEE_OFFSET, MASK_24_BITS)), _packed),
83
√ 2
⟳ 2
                    shl(PROTOCOL_FEE_OFFSET, and(MASK_24_BITS, _protocolFee))
84
                )
85
        }
86
    }
87

                            
                        
88
    function setLpFee(Slot0 _packed, uint24 _lpFee) internal pure returns (Slot0 _result) {
89
        assembly ("memory-safe") {
90
            _result :=
91
√ 1
⟳ 1
                or(and(not(shl(LP_FEE_OFFSET, MASK_24_BITS)), _packed), shl(LP_FEE_OFFSET, and(MASK_24_BITS, _lpFee)))
92
        }
93
    }
94
}
95

                            
                        

Lines covered: 0 / 20 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {CurrencyReserves} from "../src/libraries/CurrencyReserves.sol";
5
import {Test} from "forge-std/Test.sol";
6
import {Currency} from "../src/types/Currency.sol";
7

                            
                        
8
contract CurrencyReservesTest is Test {
9
    using CurrencyReserves for Currency;
10

                            
                        
11
    Currency currency0;
12

                            
                        
13
    function setUp() public {
14
        currency0 = Currency.wrap(address(0xbeef));
15
    }
16

                            
                        
17
    function test_getReserves_returns_set() public {
18
        currency0.syncCurrencyAndReserves(100);
19
        uint256 value = CurrencyReserves.getSyncedReserves();
20
        assertEq(value, 100);
21
        assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), Currency.unwrap(currency0));
22
    }
23

                            
                        
24
    function test_set_twice_returns_correct_value() public {
25
        currency0.syncCurrencyAndReserves(100);
26
        currency0.syncCurrencyAndReserves(200);
27
        uint256 value = CurrencyReserves.getSyncedReserves();
28
        assertEq(value, 200);
29
        assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), Currency.unwrap(currency0));
30
    }
31

                            
                        
32
    function test_reset_currency() public {
33
        currency0.syncCurrencyAndReserves(100);
34
        uint256 value = CurrencyReserves.getSyncedReserves();
35
        assertEq(value, 100);
36
        assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), Currency.unwrap(currency0));
37
        CurrencyReserves.resetCurrency();
38
        uint256 valueAfterReset = CurrencyReserves.getSyncedReserves();
39
        assertEq(valueAfterReset, 100);
40
        assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), address(0));
41
    }
42

                            
                        
43
    function test_reservesOfSlot() public pure {
44
        assertEq(bytes32(uint256(keccak256("ReservesOf")) - 1), CurrencyReserves.RESERVES_OF_SLOT);
45
    }
46

                            
                        
47
    function test_syncSlot() public pure {
48
        assertEq(bytes32(uint256(keccak256("Currency")) - 1), CurrencyReserves.CURRENCY_SLOT);
49
    }
50

                            
                        
51
    function test_fuzz_get_set(Currency currency, uint256 value) public {
52
        vm.assume(value != type(uint256).max);
53
        currency.syncCurrencyAndReserves(value);
54

                            
                        
55
        assertEq(Currency.unwrap(CurrencyReserves.getSyncedCurrency()), Currency.unwrap(currency));
56
        assertEq(CurrencyReserves.getSyncedReserves(), value);
57
    }
58
}
59

                            
                        

Lines covered: 0 / 139 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
6
import {Deployers} from "./utils/Deployers.sol";
7
import {FeeTakingHook} from "../src/test/FeeTakingHook.sol";
8
import {CustomCurveHook} from "../src/test/CustomCurveHook.sol";
9
import {DeltaReturningHook} from "../src/test/DeltaReturningHook.sol";
10
import {IHooks} from "../src/interfaces/IHooks.sol";
11
import {Hooks} from "../src/libraries/Hooks.sol";
12
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
13
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
14
import {Currency} from "../src/types/Currency.sol";
15
import {BalanceDelta} from "../src/types/BalanceDelta.sol";
16
import {SafeCast} from "../src/libraries/SafeCast.sol";
17

                            
                        
18
contract CustomAccountingTest is Test, Deployers, GasSnapshot {
19
    using SafeCast for *;
20

                            
                        
21
    address hook;
22

                            
                        
23
    function setUp() public {
24
        initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
25
    }
26

                            
                        
27
    function _setUpDeltaReturnFuzzPool() internal {
28
        address hookAddr = address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
29
        address impl = address(new DeltaReturningHook(manager));
30
        _etchHookAndInitPool(hookAddr, impl);
31
    }
32

                            
                        
33
    function _setUpCustomCurvePool() internal {
34
        address hookAddr = address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
35
        address impl = address(new CustomCurveHook(manager));
36
        _etchHookAndInitPool(hookAddr, impl);
37
    }
38

                            
                        
39
    function _setUpFeeTakingPool() internal {
40
        address hookAddr = address(
41
            uint160(
42
                Hooks.AFTER_SWAP_FLAG | Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG
43
                    | Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG
44
                    | Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG
45
            )
46
        );
47
        address impl = address(new FeeTakingHook(manager));
48
        _etchHookAndInitPool(hookAddr, impl);
49
    }
50

                            
                        
51
    function _etchHookAndInitPool(address hookAddr, address implAddr) internal {
52
        vm.etch(hookAddr, implAddr.code);
53
        hook = hookAddr;
54

                            
                        
55
        (key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(hookAddr), 100, SQRT_PRICE_1_1, ZERO_BYTES);
56
    }
57

                            
                        
58
    // ------------------------ SWAP  ------------------------
59

                            
                        
60
    function test_swap_afterSwapFeeOnUnspecified_exactInput() public {
61
        _setUpFeeTakingPool();
62
        uint256 balanceBefore0 = currency0.balanceOf(address(this));
63
        uint256 balanceBefore1 = currency1.balanceOf(address(this));
64

                            
                        
65
        uint256 amountToSwap = 1000;
66
        PoolSwapTest.TestSettings memory testSettings =
67
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
68
        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
69
            zeroForOne: true,
70
            amountSpecified: -int256(amountToSwap),
71
            sqrtPriceLimitX96: SQRT_PRICE_1_2
72
        });
73
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
74
        snapLastCall("swap CA fee on unspecified");
75

                            
                        
76
        // input is 1000 for output of 998 with this much liquidity available
77
        // plus a fee of 1.23% on unspecified (output) => (998*123)/10000 = 12
78
        assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amountToSwap, "amount 0");
79
        assertEq(currency1.balanceOf(address(this)), balanceBefore1 + (998 - 12), "amount 1");
80
    }
81

                            
                        
82
    function test_swap_afterSwapFeeOnUnspecified_exactOutput() public {
83
        _setUpFeeTakingPool();
84

                            
                        
85
        uint256 balanceBefore0 = currency0.balanceOf(address(this));
86
        uint256 balanceBefore1 = currency1.balanceOf(address(this));
87

                            
                        
88
        uint256 amountToSwap = 1000;
89
        PoolSwapTest.TestSettings memory testSettings =
90
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
91
        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
92
            zeroForOne: true,
93
            amountSpecified: int256(amountToSwap),
94
            sqrtPriceLimitX96: SQRT_PRICE_1_2
95
        });
96
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
97

                            
                        
98
        // input is 1002 for output of 1000 with this much liquidity available
99
        // plus a fee of 1.23% on unspecified (input) => (1002*123)/10000 = 12
100
        assertEq(currency0.balanceOf(address(this)), balanceBefore0 - 1002 - 12, "amount 0");
101
        assertEq(currency1.balanceOf(address(this)), balanceBefore1 + amountToSwap, "amount 1");
102
    }
103

                            
                        
104
    function test_swap_beforeSwapNoOpsSwap_exactInput() public {
105
        _setUpCustomCurvePool();
106

                            
                        
107
        // add liquidity by sending tokens straight into the contract
108
        key.currency0.transfer(hook, 10e18);
109
        key.currency1.transfer(hook, 10e18);
110

                            
                        
111
        uint256 balanceBefore0 = currency0.balanceOf(address(this));
112
        uint256 balanceBefore1 = currency1.balanceOf(address(this));
113

                            
                        
114
        uint256 amountToSwap = 123456;
115
        PoolSwapTest.TestSettings memory testSettings =
116
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
117
        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
118
            zeroForOne: true,
119
            amountSpecified: -int256(amountToSwap),
120
            sqrtPriceLimitX96: SQRT_PRICE_1_2
121
        });
122
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
123
        snapLastCall("swap CA custom curve + swap noop");
124

                            
                        
125
        // the custom curve hook is 1-1 linear
126
        assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amountToSwap, "amount 0");
127
        assertEq(currency1.balanceOf(address(this)), balanceBefore1 + amountToSwap, "amount 1");
128
    }
129

                            
                        
130
    function test_swap_beforeSwapNoOpsSwap_exactOutput() public {
131
        _setUpCustomCurvePool();
132

                            
                        
133
        // add liquidity by sending tokens straight into the contract
134
        key.currency0.transfer(hook, 10e18);
135
        key.currency1.transfer(hook, 10e18);
136

                            
                        
137
        uint256 balanceBefore0 = currency0.balanceOf(address(this));
138
        uint256 balanceBefore1 = currency1.balanceOf(address(this));
139

                            
                        
140
        uint256 amountToSwap = 123456;
141
        PoolSwapTest.TestSettings memory testSettings =
142
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
143
        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
144
            zeroForOne: true,
145
            amountSpecified: int256(amountToSwap),
146
            sqrtPriceLimitX96: SQRT_PRICE_1_2
147
        });
148
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
149

                            
                        
150
        // the custom curve hook is 1-1 linear
151
        assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amountToSwap, "amount 0");
152
        assertEq(currency1.balanceOf(address(this)), balanceBefore1 + amountToSwap, "amount 1");
153
    }
154

                            
                        
155
    // maximum available liquidity in each direction for the pool in test_fuzz_swap_beforeSwap_returnsDeltaSpecified
156
    int128 maxPossibleIn_fuzz_test = -6018336102428409;
157
    int128 maxPossibleOut_fuzz_test = 5981737760509662;
158

                            
                        
159
    function test_fuzz_swap_beforeSwap_returnsDeltaSpecified(
160
        int128 hookDeltaSpecified,
161
        int256 amountSpecified,
162
        bool zeroForOne
163
    ) public {
164
        // ------------------------ SETUP ------------------------
165
        Currency specifiedCurrency;
166
        bool isExactIn;
167
        _setUpDeltaReturnFuzzPool();
168

                            
                        
169
        // initialize the pool and give the hook tokens to pay into swaps
170
        key.currency0.transfer(hook, type(uint128).max);
171
        key.currency1.transfer(hook, type(uint128).max);
172

                            
                        
173
        // bound amount specified to be a fair amount less than the amount of liquidity we have
174
        amountSpecified = int128(bound(amountSpecified, -3e11, 3e11));
175
        isExactIn = amountSpecified < 0;
176
        specifiedCurrency = (isExactIn == zeroForOne) ? key.currency0 : key.currency1;
177

                            
                        
178
        // bound delta in specified to not take more than the reserves available, nor be the minimum int to
179
        // stop the hook reverting on take/settle
180
        uint128 reservesOfSpecified = uint128(specifiedCurrency.balanceOf(address(manager)));
181
        hookDeltaSpecified = int128(bound(hookDeltaSpecified, type(int128).min + 1, int128(reservesOfSpecified)));
182
        DeltaReturningHook(hook).setDeltaSpecified(hookDeltaSpecified);
183

                            
                        
184
        // setup swap variables
185
        PoolSwapTest.TestSettings memory testSettings =
186
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
187
        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
188
            zeroForOne: zeroForOne,
189
            amountSpecified: amountSpecified,
190
            sqrtPriceLimitX96: (zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT)
191
        });
192

                            
                        
193
        // ------------------------ FUZZING CASES ------------------------
194
        // with an amount specified of 0: the trade reverts
195
        if (amountSpecified == 0) {
196
            vm.expectRevert(IPoolManager.SwapAmountCannotBeZero.selector);
197
            swapRouter.swap(key, params, testSettings, ZERO_BYTES);
198

                            
                        
199
            // trade is exact input of n:, the hook cannot TAKE (+ve hookDeltaSpecified) more than n in input
200
            // otherwise the user would have to send more than n in input
201
        } else if (isExactIn && (hookDeltaSpecified > -amountSpecified)) {
202
            vm.expectRevert(Hooks.HookDeltaExceedsSwapAmount.selector);
203
            swapRouter.swap(key, params, testSettings, ZERO_BYTES);
204

                            
                        
205
            // exact output of n: the hook cannot GIVE (-ve hookDeltaSpecified) more than n in output
206
            // otherwise the user would receive more than n in output
207
        } else if (!isExactIn && (amountSpecified < -hookDeltaSpecified)) {
208
            vm.expectRevert(Hooks.HookDeltaExceedsSwapAmount.selector);
209
            swapRouter.swap(key, params, testSettings, ZERO_BYTES);
210

                            
                        
211
            // successful swaps !
212
        } else {
213
            uint256 balanceThisBefore = specifiedCurrency.balanceOf(address(this));
214
            uint256 balanceHookBefore = specifiedCurrency.balanceOf(hook);
215
            uint256 balanceManagerBefore = specifiedCurrency.balanceOf(address(manager));
216

                            
                        
217
            BalanceDelta delta = swapRouter.swap(key, params, testSettings, ZERO_BYTES);
218
            int128 deltaSpecified = (zeroForOne == isExactIn) ? delta.amount0() : delta.amount1();
219

                            
                        
220
            // in all cases the hook gets what they took, and the user gets the swap's output delta (checked more below)
221
            assertEq(
222
                balanceHookBefore.toInt256() + hookDeltaSpecified,
223
                specifiedCurrency.balanceOf(hook).toInt256(),
224
                "hook balance change incorrect"
225
            );
226
            assertEq(
227
                balanceThisBefore.toInt256() + deltaSpecified,
228
                specifiedCurrency.balanceOf(address(this)).toInt256(),
229
                "swapper balance change incorrect"
230
            );
231

                            
                        
232
            // exact input, where there arent enough input reserves available to pay swap and hook
233
            // note: all 3 values are negative, so we use <
234
            if (isExactIn && (hookDeltaSpecified + amountSpecified < maxPossibleIn_fuzz_test)) {
235
                // the hook will have taken hookDeltaSpecified of the maxPossibleIn
236
                assertEq(deltaSpecified, maxPossibleIn_fuzz_test - hookDeltaSpecified, "deltaSpecified exact input");
237
                // the manager received all possible input tokens
238
                assertEq(
239
                    balanceManagerBefore.toInt256() - maxPossibleIn_fuzz_test,
240
                    specifiedCurrency.balanceOf(address(manager)).toInt256(),
241
                    "manager balance change exact input"
242
                );
243

                            
                        
244
                // exact output, where there isnt enough output reserves available to pay swap and hook
245
            } else if (!isExactIn && (hookDeltaSpecified + amountSpecified > maxPossibleOut_fuzz_test)) {
246
                // the hook will have taken hookDeltaSpecified of the maxPossibleOut
247
                assertEq(deltaSpecified, maxPossibleOut_fuzz_test - hookDeltaSpecified, "deltaSpecified exact output");
248
                // the manager sent out all possible output tokens
249
                assertEq(
250
                    balanceManagerBefore.toInt256() - maxPossibleOut_fuzz_test,
251
                    specifiedCurrency.balanceOf(address(manager)).toInt256(),
252
                    "manager balance change exact output"
253
                );
254

                            
                        
255
                // enough reserves were available, so the user got what they desired
256
            } else {
257
                assertEq(deltaSpecified, amountSpecified, "deltaSpecified not amountSpecified");
258
                assertEq(
259
                    balanceManagerBefore.toInt256() - amountSpecified - hookDeltaSpecified,
260
                    specifiedCurrency.balanceOf(address(manager)).toInt256(),
261
                    "manager balance change not"
262
                );
263
            }
264
        }
265
    }
266

                            
                        
267
    // ------------------------ MODIFY LIQUIDITY ------------------------
268

                            
                        
269
    function test_addLiquidity_withFeeTakingHook() public {
270
        _setUpFeeTakingPool();
271

                            
                        
272
        uint256 balanceBefore0 = currency0.balanceOf(address(this));
273
        uint256 balanceBefore1 = currency1.balanceOf(address(this));
274
        uint256 hookBalanceBefore0 = currency0.balanceOf(hook);
275
        uint256 hookBalanceBefore1 = currency1.balanceOf(hook);
276
        uint256 managerBalanceBefore0 = currency0.balanceOf(address(manager));
277
        uint256 managerBalanceBefore1 = currency1.balanceOf(address(manager));
278
        // console2.log(address(key.hooks));
279
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
280
        snapLastCall("addLiquidity CA fee");
281

                            
                        
282
        uint256 hookGain0 = currency0.balanceOf(hook) - hookBalanceBefore0;
283
        uint256 hookGain1 = currency1.balanceOf(hook) - hookBalanceBefore1;
284
        uint256 thisLoss0 = balanceBefore0 - currency0.balanceOf(address(this));
285
        uint256 thisLoss1 = balanceBefore1 - currency1.balanceOf(address(this));
286
        uint256 managerGain0 = currency0.balanceOf(address(manager)) - managerBalanceBefore0;
287
        uint256 managerGain1 = currency1.balanceOf(address(manager)) - managerBalanceBefore1;
288

                            
                        
289
        // Assert that the hook got 5.43% of the added liquidity
290
        assertEq(hookGain0, managerGain0 * 543 / 10000, "hook amount 0");
291
        assertEq(hookGain1, managerGain1 * 543 / 10000, "hook amount 1");
292
        assertEq(thisLoss0 - hookGain0, managerGain0, "manager amount 0");
293
        assertEq(thisLoss1 - hookGain1, managerGain1, "manager amount 1");
294
    }
295

                            
                        
296
    function test_removeLiquidity_withFeeTakingHook() public {
297
        _setUpFeeTakingPool();
298

                            
                        
299
        uint256 balanceBefore0 = currency0.balanceOf(address(this));
300
        uint256 balanceBefore1 = currency1.balanceOf(address(this));
301
        uint256 hookBalanceBefore0 = currency0.balanceOf(hook);
302
        uint256 hookBalanceBefore1 = currency1.balanceOf(hook);
303
        uint256 managerBalanceBefore0 = currency0.balanceOf(address(manager));
304
        uint256 managerBalanceBefore1 = currency1.balanceOf(address(manager));
305

                            
                        
306
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
307
        snapLastCall("removeLiquidity CA fee");
308

                            
                        
309
        uint256 hookGain0 = currency0.balanceOf(hook) - hookBalanceBefore0;
310
        uint256 hookGain1 = currency1.balanceOf(hook) - hookBalanceBefore1;
311
        uint256 thisGain0 = currency0.balanceOf(address(this)) - balanceBefore0;
312
        uint256 thisGain1 = currency1.balanceOf(address(this)) - balanceBefore1;
313
        uint256 managerLoss0 = managerBalanceBefore0 - currency0.balanceOf(address(manager));
314
        uint256 managerLoss1 = managerBalanceBefore1 - currency1.balanceOf(address(manager));
315

                            
                        
316
        // Assert that the hook got 5.43% of the withdrawn liquidity
317
        assertEq(hookGain0, managerLoss0 * 543 / 10000, "hook amount 0");
318
        assertEq(hookGain1, managerLoss1 * 543 / 10000, "hook amount 1");
319
        assertEq(thisGain0 + hookGain0, managerLoss0, "manager amount 0");
320
        assertEq(thisGain1 + hookGain1, managerLoss1, "manager amount 1");
321
    }
322
}
323

                            
                        

Lines covered: 0 / 138 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Vm} from "forge-std/Vm.sol";
6
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
7
import {Hooks} from "../src/libraries/Hooks.sol";
8
import {LPFeeLibrary} from "../src/libraries/LPFeeLibrary.sol";
9
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
10
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
11
import {IHooks} from "../src/interfaces/IHooks.sol";
12
import {PoolKey} from "../src/types/PoolKey.sol";
13
import {PoolManager} from "../src/PoolManager.sol";
14
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
15
import {Deployers} from "./utils/Deployers.sol";
16
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
17
import {DynamicFeesTestHook} from "../src/test/DynamicFeesTestHook.sol";
18
import {Currency} from "../src/types/Currency.sol";
19
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
20
import {Pool} from "../src/libraries/Pool.sol";
21
import {BalanceDelta, BalanceDeltaLibrary} from "../src/types/BalanceDelta.sol";
22
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
23

                            
                        
24
contract TestDynamicFees is Test, Deployers, GasSnapshot {
25
    using StateLibrary for IPoolManager;
26
    using PoolIdLibrary for PoolKey;
27

                            
                        
28
    DynamicFeesTestHook dynamicFeesHooks = DynamicFeesTestHook(
29
        address(
30
            uint160(
31
                uint256(type(uint160).max) & clearAllHookPermissionsMask | Hooks.BEFORE_SWAP_FLAG
32
                    | Hooks.AFTER_INITIALIZE_FLAG
33
            )
34
        )
35
    );
36

                            
                        
37
    DynamicFeesTestHook dynamicFeesNoHooks =
38
        DynamicFeesTestHook(address(uint160(uint256(type(uint160).max) & clearAllHookPermissionsMask)));
39

                            
                        
40
    event Swap(
41
        PoolId indexed poolId,
42
        address indexed sender,
43
        int128 amount0,
44
        int128 amount1,
45
        uint160 sqrtPriceX96,
46
        uint128 liquidity,
47
        int24 tick,
48
        uint24 fee
49
    );
50

                            
                        
51
    function setUp() public {
52
        DynamicFeesTestHook impl = new DynamicFeesTestHook();
53
        vm.etch(address(dynamicFeesHooks), address(impl).code);
54
        vm.etch(address(dynamicFeesNoHooks), address(impl).code);
55

                            
                        
56
        deployFreshManagerAndRouters();
57
        dynamicFeesHooks.setManager(IPoolManager(manager));
58
        dynamicFeesNoHooks.setManager(IPoolManager(manager));
59

                            
                        
60
        deployMintAndApprove2Currencies();
61
        (key,) = initPoolAndAddLiquidity(
62
            currency0,
63
            currency1,
64
            IHooks(address(dynamicFeesHooks)),
65
            LPFeeLibrary.DYNAMIC_FEE_FLAG,
66
            SQRT_PRICE_1_1,
67
            ZERO_BYTES
68
        );
69
    }
70

                            
                        
71
    function test_updateDynamicLPFee_afterInitialize_failsWithTooLargeFee() public {
72
        key.tickSpacing = 30;
73
        uint24 fee = 1000001;
74
        dynamicFeesHooks.setFee(fee);
75

                            
                        
76
        vm.expectRevert(
77
            abi.encodeWithSelector(
78
                Hooks.FailedHookCall.selector, abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee)
79
            )
80
        );
81
        manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
82
    }
83

                            
                        
84
    function test_initialize_initializesFeeTo0() public {
85
        key.hooks = dynamicFeesNoHooks;
86

                            
                        
87
        // this fee is not fetched as theres no afterInitialize hook
88
        dynamicFeesNoHooks.setFee(1000000);
89

                            
                        
90
        manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
91
        assertEq(_fetchPoolLPFee(key), 0);
92
    }
93

                            
                        
94
    function test_updateDynamicLPFee_afterInitialize_initializesFee() public {
95
        key.tickSpacing = 30;
96
        dynamicFeesHooks.setFee(123);
97

                            
                        
98
        manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
99
        assertEq(_fetchPoolLPFee(key), 123);
100
    }
101

                            
                        
102
    function test_updateDynamicLPFee_revertsIfCallerIsntHook() public {
103
        vm.expectRevert(IPoolManager.UnauthorizedDynamicLPFeeUpdate.selector);
104
        manager.updateDynamicLPFee(key, 123);
105
    }
106

                            
                        
107
    function test_updateDynamicLPFee_revertsIfPoolHasStaticFee() public {
108
        key.fee = 3000; // static fee
109
        dynamicFeesHooks.setFee(123);
110

                            
                        
111
        // afterInitialize will try to update the fee, and fail
112
        vm.expectRevert(
113
            abi.encodeWithSelector(
114
                Hooks.FailedHookCall.selector,
115
                abi.encodeWithSelector(IPoolManager.UnauthorizedDynamicLPFeeUpdate.selector)
116
            )
117
        );
118
        manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
119
    }
120

                            
                        
121
    function test_updateDynamicLPFee_beforeSwap_failsWithTooLargeFee() public {
122
        assertEq(_fetchPoolLPFee(key), 0);
123

                            
                        
124
        uint24 fee = 1000001;
125
        dynamicFeesHooks.setFee(1000001);
126

                            
                        
127
        PoolSwapTest.TestSettings memory testSettings =
128
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
129

                            
                        
130
        vm.expectRevert(
131
            abi.encodeWithSelector(
132
                Hooks.FailedHookCall.selector, abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee)
133
            )
134
        );
135
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
136
    }
137

                            
                        
138
    function test_updateDynamicLPFee_beforeSwap_succeeds_gas() public {
139
        assertEq(_fetchPoolLPFee(key), 0);
140

                            
                        
141
        dynamicFeesHooks.setFee(123);
142

                            
                        
143
        PoolSwapTest.TestSettings memory testSettings =
144
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
145

                            
                        
146
        vm.expectEmit(true, true, true, true, address(manager));
147
        emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);
148

                            
                        
149
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
150
        snapLastCall("update dynamic fee in before swap");
151

                            
                        
152
        assertEq(_fetchPoolLPFee(key), 123);
153
    }
154

                            
                        
155
    function test_swap_100PercentLPFee_AmountIn_NoProtocol() public {
156
        assertEq(_fetchPoolLPFee(key), 0);
157

                            
                        
158
        dynamicFeesHooks.setFee(1000000);
159

                            
                        
160
        PoolSwapTest.TestSettings memory testSettings =
161
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
162

                            
                        
163
        vm.expectEmit(true, true, true, true, address(manager));
164
        emit Swap(key.toId(), address(swapRouter), -100, 0, SQRT_PRICE_1_1, 1e18, -1, 1000000);
165

                            
                        
166
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
167

                            
                        
168
        assertEq(_fetchPoolLPFee(key), 1000000);
169
    }
170

                            
                        
171
    function test_swap_50PercentLPFee_AmountIn_NoProtocol() public {
172
        assertEq(_fetchPoolLPFee(key), 0);
173

                            
                        
174
        dynamicFeesHooks.setFee(500000);
175

                            
                        
176
        PoolSwapTest.TestSettings memory testSettings =
177
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
178

                            
                        
179
        vm.expectEmit(true, true, true, true, address(manager));
180
        emit Swap(key.toId(), address(swapRouter), -100, 49, 79228162514264333632135824623, 1e18, -1, 500000);
181

                            
                        
182
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
183

                            
                        
184
        assertEq(_fetchPoolLPFee(key), 500000);
185
    }
186

                            
                        
187
    function test_swap_50PercentLPFee_AmountOut_NoProtocol() public {
188
        assertEq(_fetchPoolLPFee(key), 0);
189

                            
                        
190
        dynamicFeesHooks.setFee(500000);
191

                            
                        
192
        IPoolManager.SwapParams memory params =
193
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
194
        PoolSwapTest.TestSettings memory testSettings =
195
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
196

                            
                        
197
        vm.expectEmit(true, true, true, true, address(manager));
198
        emit Swap(key.toId(), address(swapRouter), -202, 100, 79228162514264329670727698909, 1e18, -1, 500000);
199

                            
                        
200
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
201

                            
                        
202
        assertEq(_fetchPoolLPFee(key), 500000);
203
    }
204

                            
                        
205
    function test_swap_revertsWith_InvalidFeeForExactOut_whenFeeIsMax() public {
206
        assertEq(_fetchPoolLPFee(key), 0);
207

                            
                        
208
        dynamicFeesHooks.setFee(1000000);
209

                            
                        
210
        IPoolManager.SwapParams memory params =
211
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
212
        PoolSwapTest.TestSettings memory testSettings =
213
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
214

                            
                        
215
        vm.expectRevert(Pool.InvalidFeeForExactOut.selector);
216
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
217
    }
218

                            
                        
219
    function test_swap_99PercentFee_AmountOut_WithProtocol() public {
220
        assertEq(_fetchPoolLPFee(key), 0);
221

                            
                        
222
        dynamicFeesHooks.setFee(999999);
223

                            
                        
224
        vm.prank(address(feeController));
225
        manager.setProtocolFee(key, 1000);
226

                            
                        
227
        IPoolManager.SwapParams memory params =
228
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
229
        PoolSwapTest.TestSettings memory testSettings =
230
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
231

                            
                        
232
        vm.expectEmit(true, true, true, true, address(manager));
233
        emit Swap(key.toId(), address(swapRouter), -101000000, 100, 79228162514264329670727698909, 1e18, -1, 999999);
234

                            
                        
235
        BalanceDelta delta = swapRouter.swap(key, params, testSettings, ZERO_BYTES);
236
        snapLastCall("swap with lp fee and protocol fee");
237

                            
                        
238
        uint256 expectedProtocolFee = uint256(uint128(-delta.amount0())) * 1000 / 1e6;
239
        assertEq(manager.protocolFeesAccrued(currency0), expectedProtocolFee);
240

                            
                        
241
        assertEq(_fetchPoolLPFee(key), 999999);
242
    }
243

                            
                        
244
    function test_swap_100PercentFee_AmountIn_WithProtocol() public {
245
        assertEq(_fetchPoolLPFee(key), 0);
246

                            
                        
247
        dynamicFeesHooks.setFee(1000000);
248

                            
                        
249
        vm.prank(address(feeController));
250
        manager.setProtocolFee(key, 1000);
251

                            
                        
252
        IPoolManager.SwapParams memory params =
253
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -1000, sqrtPriceLimitX96: SQRT_PRICE_1_2});
254
        PoolSwapTest.TestSettings memory testSettings =
255
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
256

                            
                        
257
        vm.expectEmit(true, true, true, true, address(manager));
258
        emit Swap(key.toId(), address(swapRouter), -1000, 0, SQRT_PRICE_1_1, 1e18, -1, 1000000);
259

                            
                        
260
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
261

                            
                        
262
        uint256 expectedProtocolFee = uint256(-params.amountSpecified) * 1000 / 1e6;
263
        assertEq(manager.protocolFeesAccrued(currency0), expectedProtocolFee);
264
    }
265

                            
                        
266
    function test_emitsSwapFee() public {
267
        assertEq(_fetchPoolLPFee(key), 0);
268

                            
                        
269
        dynamicFeesHooks.setFee(123);
270

                            
                        
271
        vm.prank(address(feeController));
272
        manager.setProtocolFee(key, 1000);
273

                            
                        
274
        PoolSwapTest.TestSettings memory testSettings =
275
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
276

                            
                        
277
        vm.expectEmit(true, true, true, true, address(manager));
278
        emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 1122);
279

                            
                        
280
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
281

                            
                        
282
        assertEq(_fetchPoolLPFee(key), 123);
283
    }
284

                            
                        
285
    function test_fuzz_ProtocolAndLPFee(uint24 lpFee, uint16 protocolFee0, uint16 protocolFee1, int256 amountSpecified)
286
        public
287
    {
288
        assertEq(_fetchPoolLPFee(key), 0);
289

                            
                        
290
        lpFee = uint16(bound(lpFee, 0, 1000000));
291
        protocolFee0 = uint16(bound(protocolFee0, 0, 1000));
292
        protocolFee1 = uint16(bound(protocolFee1, 0, 1000));
293
        vm.assume(amountSpecified != 0);
294

                            
                        
295
        uint24 protocolFee = (uint24(protocolFee1) << 12) | uint24(protocolFee0);
296
        dynamicFeesHooks.setFee(lpFee);
297

                            
                        
298
        vm.prank(address(feeController));
299
        manager.setProtocolFee(key, protocolFee);
300

                            
                        
301
        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
302
            zeroForOne: true,
303
            amountSpecified: amountSpecified,
304
            sqrtPriceLimitX96: SQRT_PRICE_1_2
305
        });
306
        PoolSwapTest.TestSettings memory testSettings =
307
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
308

                            
                        
309
        BalanceDelta delta = swapRouter.swap(key, params, testSettings, ZERO_BYTES);
310

                            
                        
311
        uint256 expectedProtocolFee = uint256(uint128(-delta.amount0())) * protocolFee0 / 1e6;
312
        assertEq(manager.protocolFeesAccrued(currency0), expectedProtocolFee);
313
    }
314

                            
                        
315
    function test_swap_withDynamicFee_gas() public {
316
        (key,) = initPoolAndAddLiquidity(
317
            currency0, currency1, dynamicFeesNoHooks, LPFeeLibrary.DYNAMIC_FEE_FLAG, SQRT_PRICE_1_1, ZERO_BYTES
318
        );
319

                            
                        
320
        assertEq(_fetchPoolLPFee(key), 0);
321
        dynamicFeesNoHooks.forcePoolFeeUpdate(key, 123);
322
        assertEq(_fetchPoolLPFee(key), 123);
323

                            
                        
324
        PoolSwapTest.TestSettings memory testSettings =
325
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
326

                            
                        
327
        vm.expectEmit(true, true, true, true, address(manager));
328
        emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);
329

                            
                        
330
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
331
        snapLastCall("swap with dynamic fee");
332
    }
333

                            
                        
334
    function _fetchPoolLPFee(PoolKey memory _key) internal view returns (uint256 lpFee) {
335
        PoolId id = _key.toId();
336
        (,,, lpFee) = manager.getSlot0(id);
337
    }
338
}
339

                            
                        

Lines covered: 0 / 62 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Vm} from "forge-std/Vm.sol";
6
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
7
import {Hooks} from "../src/libraries/Hooks.sol";
8
import {LPFeeLibrary} from "../src/libraries/LPFeeLibrary.sol";
9
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
10
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
11
import {IHooks} from "../src/interfaces/IHooks.sol";
12
import {PoolKey} from "../src/types/PoolKey.sol";
13
import {PoolManager} from "../src/PoolManager.sol";
14
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
15
import {Deployers} from "./utils/Deployers.sol";
16
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
17
import {DynamicReturnFeeTestHook} from "../src/test/DynamicReturnFeeTestHook.sol";
18
import {Currency} from "../src/types/Currency.sol";
19
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
20
import {FullMath} from "../src/libraries/FullMath.sol";
21
import {BalanceDelta} from "../src/types/BalanceDelta.sol";
22
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
23

                            
                        
24
contract TestDynamicReturnFees is Test, Deployers, GasSnapshot {
25
    using PoolIdLibrary for PoolKey;
26
    using StateLibrary for IPoolManager;
27
    using LPFeeLibrary for uint24;
28

                            
                        
29
    DynamicReturnFeeTestHook dynamicReturnFeesHook = DynamicReturnFeeTestHook(
30
        address(uint160(uint256(type(uint160).max) & clearAllHookPermissionsMask | Hooks.BEFORE_SWAP_FLAG))
31
    );
32

                            
                        
33
    event Swap(
34
        PoolId indexed poolId,
35
        address indexed sender,
36
        int128 amount0,
37
        int128 amount1,
38
        uint160 sqrtPriceX96,
39
        uint128 liquidity,
40
        int24 tick,
41
        uint24 fee
42
    );
43

                            
                        
44
    function setUp() public {
45
        DynamicReturnFeeTestHook impl = new DynamicReturnFeeTestHook();
46
        vm.etch(address(dynamicReturnFeesHook), address(impl).code);
47

                            
                        
48
        deployFreshManagerAndRouters();
49
        dynamicReturnFeesHook.setManager(IPoolManager(manager));
50

                            
                        
51
        deployMintAndApprove2Currencies();
52
        (key,) = initPoolAndAddLiquidity(
53
            currency0,
54
            currency1,
55
            IHooks(address(dynamicReturnFeesHook)),
56
            LPFeeLibrary.DYNAMIC_FEE_FLAG,
57
            SQRT_PRICE_1_1,
58
            ZERO_BYTES
59
        );
60
    }
61

                            
                        
62
    function test_fuzz_dynamicReturnSwapFee(uint24 fee) public {
63
        // hook will handle adding the override flag
64
        dynamicReturnFeesHook.setFee(fee);
65

                            
                        
66
        uint24 actualFee = fee.removeOverrideFlag();
67

                            
                        
68
        int256 amountSpecified = -10000;
69
        BalanceDelta result;
70
        if (actualFee > LPFeeLibrary.MAX_LP_FEE) {
71
            vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, actualFee));
72
            result = swap(key, true, amountSpecified, ZERO_BYTES);
73
            return;
74
        } else {
75
            result = swap(key, true, amountSpecified, ZERO_BYTES);
76
        }
77
        // BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
78
        assertEq(result.amount0(), amountSpecified);
79

                            
                        
80
        if (actualFee > LPFeeLibrary.MAX_LP_FEE) {
81
            // if the fee is too large, the fee from beforeSwap is not used (and remains at 0 -- the default value)
82
            assertApproxEqAbs(uint256(int256(result.amount1())), uint256(int256(-result.amount0())), 1 wei);
83
        } else {
84
            assertApproxEqAbs(
85
                uint256(int256(result.amount1())),
86
                FullMath.mulDiv(uint256(-amountSpecified), (1e6 - actualFee), 1e6),
87
                1 wei
88
            );
89
        }
90
    }
91

                            
                        
92
    function test_returnDynamicSwapFee_beforeSwap_succeeds_gas() public {
93
        assertEq(_fetchPoolSwapFee(key), 0);
94

                            
                        
95
        dynamicReturnFeesHook.setFee(123);
96

                            
                        
97
        PoolSwapTest.TestSettings memory testSettings =
98
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
99

                            
                        
100
        vm.expectEmit(true, true, true, true, address(manager));
101
        emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);
102

                            
                        
103
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
104
        snapLastCall("swap with return dynamic fee");
105

                            
                        
106
        assertEq(_fetchPoolSwapFee(key), 0);
107
    }
108

                            
                        
109
    function test_dynamicReturnSwapFee_initializeZeroSwapFee() public {
110
        key.tickSpacing = 30;
111
        manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
112
        assertEq(_fetchPoolSwapFee(key), 0);
113
    }
114

                            
                        
115
    function test_dynamicReturnSwapFee_notUsedIfPoolIsStaticFee() public {
116
        key.fee = 3000; // static fee
117
        dynamicReturnFeesHook.setFee(1000); // 0.10% fee is NOT used because the pool has a static fee
118

                            
                        
119
        initPoolAndAddLiquidity(
120
            currency0, currency1, IHooks(address(dynamicReturnFeesHook)), 3000, SQRT_PRICE_1_1, ZERO_BYTES
121
        );
122
        assertEq(_fetchPoolSwapFee(key), 3000);
123

                            
                        
124
        // despite returning a valid swap fee (1000), the static fee is used
125
        int256 amountSpecified = -10000;
126
        BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
127

                            
                        
128
        // after swapping ~1:1, the amount out (amount1) should be approximately 0.30% less than the amount specified
129
        assertEq(result.amount0(), amountSpecified);
130
        assertApproxEqAbs(
131
            uint256(int256(result.amount1())), FullMath.mulDiv(uint256(-amountSpecified), (1e6 - 3000), 1e6), 1 wei
132
        );
133
    }
134

                            
                        
135
    function test_dynamicReturnSwapFee_notStored() public {
136
        // fees returned by beforeSwap are not written to storage
137

                            
                        
138
        // create a new pool with an initial fee of 123
139
        key.tickSpacing = 30;
140
        manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
141
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
142
        uint24 initialFee = 123;
143
        dynamicReturnFeesHook.forcePoolFeeUpdate(key, initialFee);
144
        assertEq(_fetchPoolSwapFee(key), initialFee);
145

                            
                        
146
        // swap with a different fee
147
        uint24 newFee = 3000;
148
        dynamicReturnFeesHook.setFee(newFee);
149

                            
                        
150
        int256 amountSpecified = -10000;
151
        BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
152
        assertApproxEqAbs(
153
            uint256(int256(result.amount1())), FullMath.mulDiv(uint256(-amountSpecified), (1e6 - newFee), 1e6), 1 wei
154
        );
155

                            
                        
156
        // the fee from beforeSwap is not stored
157
        assertEq(_fetchPoolSwapFee(key), initialFee);
158
    }
159

                            
                        
160
    function test_dynamicReturnSwapFee_revertIfLPFeeTooLarge() public {
161
        assertEq(_fetchPoolSwapFee(key), 0);
162

                            
                        
163
        // hook adds the override flag
164
        uint24 fee = 1000001;
165
        dynamicReturnFeesHook.setFee(fee);
166

                            
                        
167
        // a large fee is not used
168
        int256 amountSpecified = -10000;
169
        vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee));
170
        swap(key, true, amountSpecified, ZERO_BYTES);
171
    }
172

                            
                        
173
    function _fetchPoolSwapFee(PoolKey memory _key) internal view returns (uint256 swapFee) {
174
        PoolId id = _key.toId();
175
        (,,, swapFee) = manager.getSlot0(id);
176
    }
177
}
178

                            
                        

Lines covered: 0 / 147 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.15;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Currency} from "../src/types/Currency.sol";
6
import {MockERC6909Claims} from "../src/test/MockERC6909Claims.sol";
7
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
8

                            
                        
9
contract ERC6909ClaimsTest is Test, GasSnapshot {
10
    MockERC6909Claims token;
11

                            
                        
12
    function setUp() public {
13
        token = new MockERC6909Claims();
14
    }
15

                            
                        
16
    function test_burnFrom_withApproval(address sender, uint256 id, uint256 mintAmount, uint256 transferAmount)
17
        public
18
    {
19
        token.mint(sender, id, mintAmount);
20

                            
                        
21
        vm.prank(sender);
22
        token.approve(address(this), id, mintAmount);
23

                            
                        
24
        if (transferAmount > mintAmount) {
25
            vm.expectRevert();
26
        }
27
        token.burnFrom(sender, id, transferAmount);
28

                            
                        
29
        if (transferAmount <= mintAmount) {
30
            if (mintAmount == type(uint256).max) {
31
                assertEq(token.allowance(sender, address(this), id), type(uint256).max);
32
            } else {
33
                if (sender != address(this)) {
34
                    assertEq(token.allowance(sender, address(this), id), mintAmount - transferAmount);
35
                } else {
36
                    assertEq(token.allowance(sender, address(this), id), mintAmount);
37
                }
38
            }
39
            assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
40
        }
41
    }
42

                            
                        
43
    function test_burnFrom_revertsWithNoApproval() public {
44
        token.mint(address(this), 1337, 100);
45

                            
                        
46
        vm.prank(address(0xBEEF));
47
        vm.expectRevert();
48
        token.burnFrom(address(this), 1337, 100);
49
    }
50

                            
                        
51
    /// ---- Tests copied from solmate ---- ///
52

                            
                        
53
    function testMint() public {
54
        token.mint(address(0xBEEF), 1337, 100);
55
        snapLastCall("ERC6909Claims mint");
56

                            
                        
57
        assertEq(token.balanceOf(address(0xBEEF), 1337), 100);
58
    }
59

                            
                        
60
    function testBurn() public {
61
        token.mint(address(0xBEEF), 1337, 100);
62
        vm.prank(address(0xBEEF));
63
        token.burn(1337, 70);
64
        snapLastCall("ERC6909Claims burn");
65

                            
                        
66
        assertEq(token.balanceOf(address(0xBEEF), 1337), 30);
67
    }
68

                            
                        
69
    function testSetOperator() public {
70
        token.setOperator(address(0xBEEF), true);
71

                            
                        
72
        assertTrue(token.isOperator(address(this), address(0xBEEF)));
73
    }
74

                            
                        
75
    function testApprove() public {
76
        token.approve(address(0xBEEF), 1337, 100);
77
        snapLastCall("ERC6909Claims approve");
78

                            
                        
79
        assertEq(token.allowance(address(this), address(0xBEEF), 1337), 100);
80
    }
81

                            
                        
82
    function testTransfer() public {
83
        address sender = address(0xABCD);
84

                            
                        
85
        token.mint(sender, 1337, 100);
86

                            
                        
87
        vm.prank(sender);
88

                            
                        
89
        token.transfer(address(0xBEEF), 1337, 70);
90
        snapLastCall("ERC6909Claims transfer");
91

                            
                        
92
        assertEq(token.balanceOf(sender, 1337), 30);
93
        assertEq(token.balanceOf(address(0xBEEF), 1337), 70);
94
    }
95

                            
                        
96
    function testTransferFromWithApproval() public {
97
        address sender = address(0xABCD);
98
        address receiver = address(0xBEEF);
99

                            
                        
100
        token.mint(sender, 1337, 100);
101

                            
                        
102
        vm.prank(sender);
103
        token.approve(address(this), 1337, 100);
104

                            
                        
105
        token.transferFrom(sender, receiver, 1337, 70);
106
        snapLastCall("ERC6909Claims transferFrom with approval");
107

                            
                        
108
        assertEq(token.allowance(sender, address(this), 1337), 30);
109
        assertEq(token.balanceOf(sender, 1337), 30);
110
        assertEq(token.balanceOf(receiver, 1337), 70);
111
    }
112

                            
                        
113
    function testTransferFromWithInfiniteApproval() public {
114
        address sender = address(0xABCD);
115
        address receiver = address(0xBEEF);
116

                            
                        
117
        token.mint(sender, 1337, 100);
118

                            
                        
119
        vm.prank(sender);
120
        token.approve(address(this), 1337, type(uint256).max);
121

                            
                        
122
        token.transferFrom(sender, receiver, 1337, 70);
123
        snapLastCall("ERC6909Claims transferFrom with infinite approval");
124

                            
                        
125
        assertEq(token.allowance(sender, address(this), 1337), type(uint256).max);
126
        assertEq(token.balanceOf(sender, 1337), 30);
127
        assertEq(token.balanceOf(receiver, 1337), 70);
128
    }
129

                            
                        
130
    function testTransferFromAsOperator() public {
131
        address sender = address(0xABCD);
132
        address receiver = address(0xBEEF);
133

                            
                        
134
        token.mint(sender, 1337, 100);
135

                            
                        
136
        vm.prank(sender);
137
        token.setOperator(address(this), true);
138

                            
                        
139
        token.transferFrom(sender, receiver, 1337, 70);
140
        snapLastCall("ERC6909Claims transferFrom as operator");
141

                            
                        
142
        assertEq(token.balanceOf(sender, 1337), 30);
143
        assertEq(token.balanceOf(receiver, 1337), 70);
144
    }
145

                            
                        
146
    function testFailMintBalanceOverflow() public {
147
        token.mint(address(0xDEAD), 1337, type(uint256).max);
148
        token.mint(address(0xDEAD), 1337, 1);
149
    }
150

                            
                        
151
    function testFailTransferBalanceUnderflow() public {
152
        address sender = address(0xABCD);
153
        address receiver = address(0xBEEF);
154

                            
                        
155
        vm.prank(sender);
156
        token.transferFrom(sender, receiver, 1337, 1);
157
    }
158

                            
                        
159
    function testFailTransferBalanceOverflow() public {
160
        address sender = address(0xABCD);
161
        address receiver = address(0xBEEF);
162

                            
                        
163
        token.mint(sender, 1337, type(uint256).max);
164

                            
                        
165
        vm.prank(sender);
166
        token.transferFrom(sender, receiver, 1337, type(uint256).max);
167

                            
                        
168
        token.mint(sender, 1337, 1);
169

                            
                        
170
        vm.prank(sender);
171
        token.transferFrom(sender, receiver, 1337, 1);
172
    }
173

                            
                        
174
    function testFailTransferFromBalanceUnderflow() public {
175
        address sender = address(0xABCD);
176
        address receiver = address(0xBEEF);
177

                            
                        
178
        vm.prank(sender);
179
        token.transferFrom(sender, receiver, 1337, 1);
180
    }
181

                            
                        
182
    function testFailTransferFromBalanceOverflow() public {
183
        address sender = address(0xABCD);
184
        address receiver = address(0xBEEF);
185

                            
                        
186
        token.mint(sender, 1337, type(uint256).max);
187

                            
                        
188
        vm.prank(sender);
189
        token.transferFrom(sender, receiver, 1337, type(uint256).max);
190

                            
                        
191
        token.mint(sender, 1337, 1);
192

                            
                        
193
        vm.prank(sender);
194
        token.transferFrom(sender, receiver, 1337, 1);
195
    }
196

                            
                        
197
    function testFailTransferFromNotAuthorized() public {
198
        address sender = address(0xABCD);
199
        address receiver = address(0xBEEF);
200

                            
                        
201
        token.mint(sender, 1337, 100);
202

                            
                        
203
        token.transferFrom(sender, receiver, 1337, 100);
204
    }
205

                            
                        
206
    function testMint(address receiver, uint256 id, uint256 amount) public {
207
        token.mint(receiver, id, amount);
208

                            
                        
209
        assertEq(token.balanceOf(receiver, id), amount);
210
    }
211

                            
                        
212
    function testBurn(address sender, uint256 id, uint256 amount) public {
213
        token.mint(sender, id, amount);
214
        vm.prank(sender);
215
        token.burn(id, amount);
216

                            
                        
217
        assertEq(token.balanceOf(sender, id), 0);
218
    }
219

                            
                        
220
    function testSetOperator(address operator, bool approved) public {
221
        token.setOperator(operator, approved);
222

                            
                        
223
        assertEq(token.isOperator(address(this), operator), approved);
224
    }
225

                            
                        
226
    function testApprove(address spender, uint256 id, uint256 amount) public {
227
        token.approve(spender, id, amount);
228

                            
                        
229
        assertEq(token.allowance(address(this), spender, id), amount);
230
    }
231

                            
                        
232
    function testTransfer(address sender, address receiver, uint256 id, uint256 mintAmount, uint256 transferAmount)
233
        public
234
    {
235
        transferAmount = bound(transferAmount, 0, mintAmount);
236

                            
                        
237
        token.mint(sender, id, mintAmount);
238

                            
                        
239
        vm.prank(sender);
240
        token.transfer(receiver, id, transferAmount);
241

                            
                        
242
        if (sender == receiver) {
243
            assertEq(token.balanceOf(sender, id), mintAmount);
244
        } else {
245
            assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
246
            assertEq(token.balanceOf(receiver, id), transferAmount);
247
        }
248
    }
249

                            
                        
250
    function testTransferFromWithApproval(
251
        address sender,
252
        address receiver,
253
        uint256 id,
254
        uint256 mintAmount,
255
        uint256 transferAmount
256
    ) public {
257
        transferAmount = bound(transferAmount, 0, mintAmount);
258

                            
                        
259
        token.mint(sender, id, mintAmount);
260

                            
                        
261
        vm.prank(sender);
262
        token.approve(address(this), id, mintAmount);
263

                            
                        
264
        token.transferFrom(sender, receiver, id, transferAmount);
265

                            
                        
266
        if (mintAmount == type(uint256).max) {
267
            assertEq(token.allowance(sender, address(this), id), type(uint256).max);
268
        } else {
269
            if (sender != address(this)) {
270
                assertEq(token.allowance(sender, address(this), id), mintAmount - transferAmount);
271
            } else {
272
                assertEq(token.allowance(sender, address(this), id), mintAmount);
273
            }
274
        }
275

                            
                        
276
        if (sender == receiver) {
277
            assertEq(token.balanceOf(sender, id), mintAmount);
278
        } else {
279
            assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
280
            assertEq(token.balanceOf(receiver, id), transferAmount);
281
        }
282
    }
283

                            
                        
284
    function testTransferFromWithInfiniteApproval(
285
        address sender,
286
        address receiver,
287
        uint256 id,
288
        uint256 mintAmount,
289
        uint256 transferAmount
290
    ) public {
291
        transferAmount = bound(transferAmount, 0, mintAmount);
292

                            
                        
293
        token.mint(sender, id, mintAmount);
294

                            
                        
295
        vm.prank(sender);
296
        token.approve(address(this), id, type(uint256).max);
297

                            
                        
298
        token.transferFrom(sender, receiver, id, transferAmount);
299

                            
                        
300
        assertEq(token.allowance(sender, address(this), id), type(uint256).max);
301

                            
                        
302
        if (sender == receiver) {
303
            assertEq(token.balanceOf(sender, id), mintAmount);
304
        } else {
305
            assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
306
            assertEq(token.balanceOf(receiver, id), transferAmount);
307
        }
308
    }
309

                            
                        
310
    function testTransferFromAsOperator(
311
        address sender,
312
        address receiver,
313
        uint256 id,
314
        uint256 mintAmount,
315
        uint256 transferAmount
316
    ) public {
317
        transferAmount = bound(transferAmount, 0, mintAmount);
318

                            
                        
319
        token.mint(sender, id, mintAmount);
320

                            
                        
321
        vm.prank(sender);
322
        token.setOperator(address(this), true);
323

                            
                        
324
        token.transferFrom(sender, receiver, id, transferAmount);
325

                            
                        
326
        if (sender == receiver) {
327
            assertEq(token.balanceOf(sender, id), mintAmount);
328
        } else {
329
            assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
330
            assertEq(token.balanceOf(receiver, id), transferAmount);
331
        }
332
    }
333

                            
                        
334
    function testFailTransferBalanceUnderflow(address sender, address receiver, uint256 id, uint256 amount) public {
335
        amount = bound(amount, 1, type(uint256).max);
336

                            
                        
337
        vm.prank(sender);
338
        token.transfer(receiver, id, amount);
339
    }
340

                            
                        
341
    function testFailTransferBalanceOverflow(address sender, address receiver, uint256 id, uint256 amount) public {
342
        amount = bound(amount, 1, type(uint256).max);
343
        uint256 overflowAmount = type(uint256).max - amount + 1;
344

                            
                        
345
        token.mint(sender, id, amount);
346

                            
                        
347
        vm.prank(sender);
348
        token.transfer(receiver, id, amount);
349

                            
                        
350
        token.mint(sender, id, overflowAmount);
351

                            
                        
352
        vm.prank(sender);
353
        token.transfer(receiver, id, overflowAmount);
354
    }
355

                            
                        
356
    function testFailTransferFromBalanceUnderflow(address sender, address receiver, uint256 id, uint256 amount)
357
        public
358
    {
359
        amount = bound(amount, 1, type(uint256).max);
360

                            
                        
361
        vm.prank(sender);
362
        token.transferFrom(sender, receiver, id, amount);
363
    }
364

                            
                        
365
    function testFailTransferFromBalanceOverflow(address sender, address receiver, uint256 id, uint256 amount) public {
366
        amount = bound(amount, 1, type(uint256).max);
367
        uint256 overflowAmount = type(uint256).max - amount + 1;
368

                            
                        
369
        token.mint(sender, id, amount);
370

                            
                        
371
        vm.prank(sender);
372
        token.transferFrom(sender, receiver, id, amount);
373

                            
                        
374
        token.mint(sender, id, overflowAmount);
375

                            
                        
376
        vm.prank(sender);
377
        token.transferFrom(sender, receiver, id, overflowAmount);
378
    }
379

                            
                        
380
    function testFailTransferFromNotAuthorized(address sender, address receiver, uint256 id, uint256 amount) public {
381
        amount = bound(amount, 1, type(uint256).max);
382

                            
                        
383
        token.mint(sender, id, amount);
384

                            
                        
385
        vm.assume(sender != address(this));
386
        token.transferFrom(sender, receiver, id, amount);
387
    }
388
}
389

                            
                        

Lines covered: 0 / 34 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Extsload} from "../src/Extsload.sol";
6
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
7

                            
                        
8
contract Loadable is Extsload {}
9

                            
                        
10
/// @author philogy <https://github.com/philogy>
11
contract ExtsloadTest is Test, GasSnapshot {
12
    Loadable loadable = new Loadable();
13

                            
                        
14
    function test_load10_sparse() public {
15
        bytes32[] memory keys = new bytes32[](10);
16
        for (uint256 i = 0; i < keys.length; i++) {
17
            keys[i] = keccak256(abi.encode(i));
18
            vm.store(address(loadable), keys[i], bytes32(i));
19
        }
20

                            
                        
21
        bytes32[] memory values = loadable.extsload(keys);
22
        snapLastCall("sparse external sload");
23
        assertEq(values.length, keys.length);
24
        for (uint256 i = 0; i < values.length; i++) {
25
            assertEq(values[i], bytes32(i));
26
        }
27
    }
28

                            
                        
29
    function test_fuzz_consecutiveExtsload(uint256 startSlot, uint256 length, uint256 seed) public {
30
        length = bound(length, 0, 1000);
31
        startSlot = bound(startSlot, 0, type(uint256).max - length);
32
        for (uint256 i; i < length; ++i) {
33
            vm.store(address(loadable), bytes32(startSlot + i), keccak256(abi.encode(i, seed)));
34
        }
35
        bytes32[] memory values = loadable.extsload(bytes32(startSlot), length);
36
        assertEq(values.length, length);
37
        for (uint256 i; i < length; ++i) {
38
            assertEq(values[i], keccak256(abi.encode(i, seed)));
39
        }
40
    }
41

                            
                        
42
    function test_fuzz_extsload(uint256 length, uint256 seed, bytes memory dirtyBits) public {
43
        length = bound(length, 0, 1000);
44
        bytes32[] memory slots = new bytes32[](length);
45
        bytes32[] memory expected = new bytes32[](length);
46
        for (uint256 i; i < length; ++i) {
47
            slots[i] = keccak256(abi.encode(i, seed));
48
            expected[i] = keccak256(abi.encode(slots[i]));
49
            vm.store(address(loadable), slots[i], expected[i]);
50
        }
51
        bytes32[] memory values = loadable.extsload(slots);
52
        assertEq(values, expected);
53
        // test with dirty bits
54
        bytes memory data = abi.encodeWithSignature("extsload(bytes32[])", (slots));
55
        bytes memory malformedData = bytes.concat(data, dirtyBits);
56
        (bool success, bytes memory returnData) = address(loadable).staticcall(malformedData);
57
        assertTrue(success, "extsload failed");
58
        assertEq(returnData.length % 0x20, 0, "return data length is not a multiple of 32");
59
        assertEq(abi.decode(returnData, (bytes32[])), expected);
60
    }
61
}
62

                            
                        

Lines covered: 0 / 132 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Deployers} from "./utils/Deployers.sol";
6
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
9
import {IHooks} from "src/interfaces/IHooks.sol";
10
import {Position} from "src/libraries/Position.sol";
11
import {PoolId} from "src/types/PoolId.sol";
12
import {PoolModifyLiquidityTest} from "../src/test/PoolModifyLiquidityTest.sol";
13
import {Constants} from "./utils/Constants.sol";
14
import {Currency} from "src/types/Currency.sol";
15
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
16
import {StateLibrary} from "src/libraries/StateLibrary.sol";
17
import {JavascriptFfi} from "./utils/JavascriptFfi.sol";
18
import {BalanceDelta} from "../src/types/BalanceDelta.sol";
19
import {Fuzzers} from "../src/test/Fuzzers.sol";
20
import {TickMath} from "src/libraries/TickMath.sol";
21
import {toBalanceDelta} from "src/types/BalanceDelta.sol";
22
import {Logger} from "./utils/Logger.sol";
23

                            
                        
24
contract ModifyLiquidityTest is Test, Logger, Deployers, JavascriptFfi, Fuzzers, GasSnapshot {
25
    using StateLibrary for IPoolManager;
26

                            
                        
27
    PoolKey simpleKey; // vanilla pool key
28
    PoolId simplePoolId; // id for vanilla pool key
29

                            
                        
30
    bytes32 SALT = hex"CAFF";
31

                            
                        
32
    int128 constant ONE_PIP = 1e6;
33

                            
                        
34
    IPoolManager.ModifyLiquidityParams public LIQ_PARAM_NO_SALT =
35
        IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: 0});
36

                            
                        
37
    IPoolManager.ModifyLiquidityParams public LIQ_PARAM_SALT =
38
        IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: SALT});
39

                            
                        
40
    function setUp() public {
41
        deployFreshManagerAndRouters();
42
        deployMintAndApprove2Currencies();
43
        (simpleKey, simplePoolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES);
44
    }
45

                            
                        
46
    /*//////////////////////////////////////////////////////////////
47
                            Fuzz Add Liquidity
48
    //////////////////////////////////////////////////////////////*/
49

                            
                        
50
    /// forge-config: default.fuzz.runs = 10
51
    /// forge-config: pr.fuzz.runs = 10
52
    /// forge-config: ci.fuzz.runs = 500
53
    function test_ffi_fuzz_addLiquidity_defaultPool_ReturnsCorrectLiquidityDelta(
54
        IPoolManager.ModifyLiquidityParams memory paramSeed
55
    ) public {
56
        // Sanitize the fuzzed params to get valid tickLower, tickUpper, and liquidityDelta.
57
        // We use SQRT_PRICE_1_1 because the simpleKey pool has initial sqrtPrice of SQRT_PRICE_1_1.
58
        IPoolManager.ModifyLiquidityParams memory params =
59
            createFuzzyLiquidityParams(simpleKey, paramSeed, SQRT_PRICE_1_1);
60

                            
                        
61
        logParams(params);
62

                            
                        
63
        (BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(simpleKey, params, ZERO_BYTES);
64

                            
                        
65
        (int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(simplePoolId, params);
66

                            
                        
67
        _checkError(delta.amount0(), jsDelta0, "amount0 is off by more than one pip");
68
        _checkError(delta.amount1(), jsDelta1, "amount1 is off by more than one pip");
69
    }
70

                            
                        
71
    // Static edge case, no fuzz test, to make sure we test max tickspacing.
72
    function test_ffi_addLiqudity_weirdPool_0_returnsCorrectLiquidityDelta() public {
73
        // Use a pool with TickSpacing of MAX_TICK_SPACING
74
        (PoolKey memory wp0, PoolId wpId0) = initPool(
75
            currency0, currency1, IHooks(address(0)), 500, TickMath.MAX_TICK_SPACING, SQRT_PRICE_1_1, ZERO_BYTES
76
        );
77

                            
                        
78
        // Set the params to add random amount of liquidity to random tick boundary.
79
        int24 tickUpper = TickMath.MAX_TICK_SPACING * 4;
80
        int24 tickLower = TickMath.MAX_TICK_SPACING * -9;
81
        IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams({
82
            tickLower: tickLower,
83
            tickUpper: tickUpper,
84
            liquidityDelta: 16787899214600939458,
85
            salt: 0
86
        });
87

                            
                        
88
        (BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(wp0, params, ZERO_BYTES);
89

                            
                        
90
        (int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(wpId0, params);
91

                            
                        
92
        _checkError(delta.amount0(), jsDelta0, "amount0 is off by more than one pip");
93
        _checkError(delta.amount1(), jsDelta1, "amount1 is off by more than one pip");
94
    }
95

                            
                        
96
    // Static edge case, no fuzz test, to make sure we test min tick spacing.
97
    function test_ffi_addLiqudity_weirdPool_1_returnsCorrectLiquidityDelta() public {
98
        // Use a pool with TickSpacing of MIN_TICK_SPACING
99
        (PoolKey memory wp0, PoolId wpId0) = initPool(
100
            currency0, currency1, IHooks(address(0)), 551, TickMath.MIN_TICK_SPACING, SQRT_PRICE_1_1, ZERO_BYTES
101
        );
102

                            
                        
103
        // Set the params to add random amount of liquidity to random tick boundary.
104
        int24 tickUpper = TickMath.MIN_TICK_SPACING * 17;
105
        int24 tickLower = TickMath.MIN_TICK_SPACING * 9;
106
        IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams({
107
            tickLower: tickLower,
108
            tickUpper: tickUpper,
109
            liquidityDelta: 922871614499955267459963,
110
            salt: 0
111
        });
112

                            
                        
113
        params.tickLower = 10;
114

                            
                        
115
        (BalanceDelta delta) = modifyLiquidityRouter.modifyLiquidity(wp0, params, ZERO_BYTES);
116

                            
                        
117
        (int128 jsDelta0, int128 jsDelta1) = _modifyLiquidityJS(wpId0, params);
118

                            
                        
119
        _checkError(delta.amount0(), jsDelta0, "amount0 is off by more than one pip");
120
        _checkError(delta.amount1(), jsDelta1, "amount1 is off by more than one pip");
121
    }
122

                            
                        
123
    function _modifyLiquidityJS(PoolId poolId, IPoolManager.ModifyLiquidityParams memory params)
124
        public
125
        returns (int128, int128)
126
    {
127
        (uint256 price, int24 tick,,) = manager.getSlot0(poolId);
128

                            
                        
129
        string memory jsParameters = string(
130
            abi.encodePacked(
131
                vm.toString(params.tickLower),
132
                ",",
133
                vm.toString(params.tickUpper),
134
                ",",
135
                vm.toString(params.liquidityDelta),
136
                ",",
137
                vm.toString(tick),
138
                ",",
139
                vm.toString(price)
140
            )
141
        );
142

                            
                        
143
        string memory scriptName = "forge-test-getModifyLiquidityResult";
144
        bytes memory jsResult = runScript(scriptName, jsParameters);
145

                            
                        
146
        int128[] memory result = abi.decode(jsResult, (int128[]));
147
        int128 jsDelta0 = result[0];
148
        int128 jsDelta1 = result[1];
149
        return (jsDelta0, jsDelta1);
150
    }
151

                            
                        
152
    // assert solc/js result is at most off by 1/100th of a bip (aka one pip)
153
    function _checkError(int128 solc, int128 js, string memory errMsg) public pure {
154
        if (solc != js) {
155
            // Ensures no div by 0 in the case of one-sided liquidity adds.
156
            (int128 gtResult, int128 ltResult) = js > solc ? (js, solc) : (solc, js);
157
            int128 resultsDiff = gtResult - ltResult;
158
            assertEq(resultsDiff * ONE_PIP / js, 0, errMsg);
159
        }
160
    }
161

                            
                        
162
    /*//////////////////////////////////////////////////////////////
163
                            Salt
164
    //////////////////////////////////////////////////////////////*/
165

                            
                        
166
    function test_modifyLiquidity_samePosition_zeroSalt_isUpdated() public {
167
        Position.Info memory position = manager.getPosition(
168
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0
169
        );
170
        assertEq(position.liquidity, 0);
171
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_NO_SALT, ZERO_BYTES);
172
        position = manager.getPosition(
173
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0
174
        );
175

                            
                        
176
        assertEq(position.liquidity, uint128(uint256(LIQ_PARAM_NO_SALT.liquidityDelta)));
177

                            
                        
178
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_NO_SALT, ZERO_BYTES);
179
        Position.Info memory updated = manager.getPosition(
180
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0
181
        );
182
        assertEq(updated.liquidity, position.liquidity + uint128(uint256(LIQ_PARAM_NO_SALT.liquidityDelta)));
183
    }
184

                            
                        
185
    function test_modifyLiquidity_samePosition_withSalt_isUpdated() public {
186
        Position.Info memory position = manager.getPosition(
187
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
188
        );
189
        assertEq(position.liquidity, 0);
190
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES);
191
        position = manager.getPosition(
192
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
193
        );
194
        assertEq(position.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta)));
195

                            
                        
196
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES);
197
        Position.Info memory updated = manager.getPosition(
198
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
199
        );
200
        assertEq(updated.liquidity, position.liquidity + uint128(uint256(LIQ_PARAM_SALT.liquidityDelta)));
201
    }
202

                            
                        
203
    function test_modifyLiquidity_sameTicks_withDifferentSalt_isNotUpdated() public {
204
        Position.Info memory positionNoSalt = manager.getPosition(
205
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0
206
        );
207

                            
                        
208
        Position.Info memory positionSalt = manager.getPosition(
209
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
210
        );
211
        assertEq(positionNoSalt.liquidity, 0);
212
        assertEq(positionSalt.liquidity, 0);
213

                            
                        
214
        // Modify the liquidity with the salt.
215
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES);
216

                            
                        
217
        positionNoSalt = manager.getPosition(
218
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0
219
        );
220

                            
                        
221
        positionSalt = manager.getPosition(
222
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
223
        );
224

                            
                        
225
        assertEq(positionNoSalt.liquidity, 0); // This position does not have liquidity.
226
        assertEq(positionSalt.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta))); // This position does.
227

                            
                        
228
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_NO_SALT, ZERO_BYTES); // Now the positions should have the same liquidity.
229

                            
                        
230
        positionNoSalt = manager.getPosition(
231
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0
232
        );
233

                            
                        
234
        positionSalt = manager.getPosition(
235
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
236
        );
237

                            
                        
238
        // positionSalt should still only have the original liquidity deposited to it
239
        assertEq(positionSalt.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta)));
240
        assertEq(positionNoSalt.liquidity, positionSalt.liquidity);
241

                            
                        
242
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES);
243
        Position.Info memory updatedWithSalt = manager.getPosition(
244
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
245
        );
246
        Position.Info memory updatedNoSalt = manager.getPosition(
247
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_NO_SALT.tickLower, LIQ_PARAM_NO_SALT.tickUpper, 0
248
        );
249

                            
                        
250
        assertEq(updatedWithSalt.liquidity, positionSalt.liquidity + uint128(uint256(LIQ_PARAM_SALT.liquidityDelta)));
251
        assertGt(updatedWithSalt.liquidity, updatedNoSalt.liquidity);
252
        assertEq(updatedNoSalt.liquidity, positionNoSalt.liquidity);
253
    }
254

                            
                        
255
    function test_modifyLiquidity_sameSalt_differentLiquidityRouters_doNotEditSamePosition() public {
256
        // Set up new router.
257
        PoolModifyLiquidityTest modifyLiquidityRouter2 = new PoolModifyLiquidityTest(manager);
258

                            
                        
259
        MockERC20(Currency.unwrap(currency0)).approve(address(modifyLiquidityRouter2), Constants.MAX_UINT256);
260
        MockERC20(Currency.unwrap(currency1)).approve(address(modifyLiquidityRouter2), Constants.MAX_UINT256);
261

                            
                        
262
        IPoolManager.ModifyLiquidityParams memory LIQ_PARAM_SALT_2 =
263
            IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 2e18, salt: SALT});
264

                            
                        
265
        // Get the uninitialized positions and assert they have no liquidity.
266
        Position.Info memory positionSalt = manager.getPosition(
267
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
268
        );
269

                            
                        
270
        Position.Info memory positionSalt2 = manager.getPosition(
271
            simplePoolId, address(modifyLiquidityRouter2), LIQ_PARAM_SALT_2.tickLower, LIQ_PARAM_SALT_2.tickUpper, SALT
272
        );
273

                            
                        
274
        assertEq(positionSalt.liquidity, 0);
275
        assertEq(positionSalt2.liquidity, 0);
276

                            
                        
277
        // Modify the liquidity with the salt with the first router.
278
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES);
279

                            
                        
280
        Position.Info memory updatedPositionSalt = manager.getPosition(
281
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
282
        );
283

                            
                        
284
        Position.Info memory updatedPositionSalt2 = manager.getPosition(
285
            simplePoolId, address(modifyLiquidityRouter2), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
286
        );
287

                            
                        
288
        // Assert only the liquidity from the first router is updated.
289
        assertEq(updatedPositionSalt.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta)));
290
        assertEq(updatedPositionSalt2.liquidity, 0);
291

                            
                        
292
        // Modify the liquidity with the second router.
293
        modifyLiquidityRouter2.modifyLiquidity(simpleKey, LIQ_PARAM_SALT_2, ZERO_BYTES);
294

                            
                        
295
        updatedPositionSalt2 = manager.getPosition(
296
            simplePoolId, address(modifyLiquidityRouter2), LIQ_PARAM_SALT_2.tickLower, LIQ_PARAM_SALT_2.tickUpper, SALT
297
        );
298
        updatedPositionSalt = manager.getPosition(
299
            simplePoolId, address(modifyLiquidityRouter), LIQ_PARAM_SALT.tickLower, LIQ_PARAM_SALT.tickUpper, SALT
300
        );
301

                            
                        
302
        // Assert only the liquidity from the second router is updated.
303
        assertEq(updatedPositionSalt2.liquidity, uint128(uint256(LIQ_PARAM_SALT_2.liquidityDelta)));
304
        assertEq(updatedPositionSalt.liquidity, uint128(uint256(LIQ_PARAM_SALT.liquidityDelta)));
305
    }
306

                            
                        
307
    function test_gas_modifyLiquidity_newPosition() public {
308
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES);
309
        snapLastCall("create new liquidity to a position with salt");
310
    }
311

                            
                        
312
    function test_gas_modifyLiquidity_updateSamePosition_withSalt() public {
313
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES);
314
        modifyLiquidityRouter.modifyLiquidity(simpleKey, LIQ_PARAM_SALT, ZERO_BYTES);
315
        snapLastCall("add liquidity to already existing position with salt");
316
    }
317
}
318

                            
                        

Lines covered: 0 / 27 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
5
import {Test} from "forge-std/Test.sol";
6
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
7
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
8
import {ProxyPoolManager} from "../src/test/ProxyPoolManager.sol";
9
import {NoDelegateCallTest} from "../src/test/NoDelegateCallTest.sol";
10
import {PoolManager} from "../src/PoolManager.sol";
11
import {NoDelegateCall} from "../src/NoDelegateCall.sol";
12
import {Deployers} from "./utils/Deployers.sol";
13

                            
                        
14
contract TestDelegateCall is Test, Deployers, GasSnapshot {
15
    // override to use ProxyPoolManager
16
    function deployFreshManager() internal virtual override {
17
        IPoolManager delegateManager = new PoolManager(500000);
18
        manager = new ProxyPoolManager(address(delegateManager), 500000);
19
    }
20

                            
                        
21
    NoDelegateCallTest noDelegateCallTest;
22

                            
                        
23
    function setUp() public {
24
        deployFreshManagerAndRouters();
25

                            
                        
26
        noDelegateCallTest = new NoDelegateCallTest();
27
    }
28

                            
                        
29
    function test_gas_noDelegateCall() public {
30
        snap(
31
            "NoDelegateCall",
32
            noDelegateCallTest.getGasCostOfCannotBeDelegateCalled()
33
                - noDelegateCallTest.getGasCostOfCanBeDelegateCalled()
34
        );
35
    }
36

                            
                        
37
    function test_delegateCallNoModifier() public {
38
        (bool success,) =
39
            address(noDelegateCallTest).delegatecall(abi.encode(noDelegateCallTest.canBeDelegateCalled.selector));
40
        assertTrue(success);
41
    }
42

                            
                        
43
    function test_delegateCallWithModifier_revertsWithDelegateCallNotAllowed() public {
44
        vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector);
45
        (bool success,) =
46
            address(noDelegateCallTest).delegatecall(abi.encode(noDelegateCallTest.cannotBeDelegateCalled.selector));
47
        // note vm.expectRevert inverts success, so a true result here means it reverted
48
        assertTrue(success);
49
    }
50

                            
                        
51
    function test_externalCallToPrivateMethodWithModifer_succeeds() public view {
52
        noDelegateCallTest.callsIntoNoDelegateCallFunction();
53
    }
54

                            
                        
55
    function test_delegateCallFromExternalToPrivateMethodWithModifier_revertsWithDelegateCallNotAllowed() public {
56
        vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector);
57
        (bool success,) = address(noDelegateCallTest).delegatecall(
58
            abi.encode(noDelegateCallTest.callsIntoNoDelegateCallFunction.selector)
59
        );
60
        // note vm.expectRevert inverts success, so a true result here means it reverted
61
        assertTrue(success);
62
    }
63

                            
                        
64
    function test_modifyLiquidity_noDelegateCall() public {
65
        vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector);
66
        modifyLiquidityRouter.modifyLiquidity(uninitializedKey, LIQUIDITY_PARAMS, ZERO_BYTES);
67

                            
                        
68
        vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector);
69
        modifyLiquidityRouter.modifyLiquidity(uninitializedKey, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
70
    }
71

                            
                        
72
    function test_swap_noDelegateCall() public {
73
        PoolSwapTest.TestSettings memory testSettings =
74
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
75

                            
                        
76
        vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector);
77
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
78
    }
79

                            
                        
80
    function test_donate_noDelegateCall() public {
81
        vm.expectRevert(NoDelegateCall.DelegateCallNotAllowed.selector);
82
        donateRouter.donate(key, 100, 200, ZERO_BYTES);
83
    }
84
}
85

                            
                        

Lines covered: 0 / 108 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.0;
3

                            
                        
4
import "forge-std/Test.sol";
5
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
6
import {Deployers} from "./utils/Deployers.sol";
7
import {Actions} from "../src/test/ActionsRouter.sol";
8
import {IHooks} from "../src/interfaces/IHooks.sol";
9
import {MockERC20} from "forge-std/mocks/MockERC20.sol";
10
import {Currency} from "../src/types/Currency.sol";
11

                            
                        
12
contract ClearTest is Test, Deployers {
13
    function setUp() public {
14
        initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
15
        seedMoreLiquidity(key, 10e18, 10e18);
16
    }
17

                            
                        
18
    function test_clear_reverts_negativeDelta() external {
19
        uint256 amount = 1e18;
20

                            
                        
21
        Actions[] memory actions = new Actions[](2);
22
        bytes[] memory params = new bytes[](2);
23

                            
                        
24
        // Apply a negative delta.
25
        actions[0] = Actions.TAKE;
26
        params[0] = abi.encode(currency0, address(this), amount);
27

                            
                        
28
        actions[1] = Actions.CLEAR;
29
        params[1] = abi.encode(currency0, amount, false, "");
30

                            
                        
31
        vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector);
32
        actionsRouter.executeActions(actions, params);
33
    }
34

                            
                        
35
    function test_clear_reverts_positiveDelta_inputGreaterThanDelta() external {
36
        uint256 amount = 1e18;
37
        Actions[] memory actions = new Actions[](5);
38
        bytes[] memory params = new bytes[](5);
39

                            
                        
40
        // Apply a positive delta.
41
        actions[0] = Actions.SYNC;
42
        params[0] = abi.encode(currency0);
43

                            
                        
44
        actions[1] = Actions.TRANSFER_FROM;
45
        params[1] = abi.encode(currency0, address(this), address(manager), amount);
46

                            
                        
47
        actions[2] = Actions.SETTLE;
48
        params[2] = abi.encode(currency0);
49

                            
                        
50
        // Delta should be equal to the positive amount.
51
        actions[3] = Actions.ASSERT_DELTA_EQUALS;
52
        params[3] = abi.encode(currency0, address(actionsRouter), amount);
53

                            
                        
54
        // Clear for 1 greater than the delta.
55
        actions[4] = Actions.CLEAR;
56
        params[4] = abi.encode(currency0, amount + 1, false, "");
57

                            
                        
58
        vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector);
59
        actionsRouter.executeActions(actions, params);
60
    }
61

                            
                        
62
    function test_clear_reverts_positiveDelta_inputLessThanDelta() external {
63
        uint256 amount = 1e18;
64
        Actions[] memory actions = new Actions[](5);
65
        bytes[] memory params = new bytes[](5);
66

                            
                        
67
        // Apply a positive delta.
68
        actions[0] = Actions.SYNC;
69
        params[0] = abi.encode(currency0);
70

                            
                        
71
        actions[1] = Actions.TRANSFER_FROM;
72
        params[1] = abi.encode(currency0, address(this), address(manager), amount);
73

                            
                        
74
        actions[2] = Actions.SETTLE;
75
        params[2] = abi.encode(currency0);
76

                            
                        
77
        actions[3] = Actions.ASSERT_DELTA_EQUALS;
78
        params[3] = abi.encode(currency0, address(actionsRouter), amount);
79

                            
                        
80
        // Clear for 1 less than the delta.
81
        actions[4] = Actions.CLEAR;
82
        params[4] = abi.encode(currency0, amount - 1, false, "");
83

                            
                        
84
        vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector);
85
        actionsRouter.executeActions(actions, params);
86
    }
87

                            
                        
88
    function test_clear_reverts_positiveDelta_inputZero() external {
89
        uint256 amount = 1e18;
90
        Actions[] memory actions = new Actions[](5);
91
        bytes[] memory params = new bytes[](5);
92

                            
                        
93
        // Apply a positive delta.
94
        actions[0] = Actions.SYNC;
95
        params[0] = abi.encode(currency0);
96

                            
                        
97
        actions[1] = Actions.TRANSFER_FROM;
98
        params[1] = abi.encode(currency0, address(this), address(manager), amount);
99

                            
                        
100
        actions[2] = Actions.SETTLE;
101
        params[2] = abi.encode(currency0);
102

                            
                        
103
        actions[3] = Actions.ASSERT_DELTA_EQUALS;
104
        params[3] = abi.encode(currency0, address(actionsRouter), amount);
105

                            
                        
106
        // Clear with 0.
107
        actions[4] = Actions.CLEAR;
108
        params[4] = abi.encode(currency0, 0, false, "");
109

                            
                        
110
        vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector);
111
        actionsRouter.executeActions(actions, params);
112
    }
113

                            
                        
114
    function test_clear_zeroDelta_inputZero_isUnchanged() external {
115
        Actions[] memory actions = new Actions[](5);
116
        bytes[] memory params = new bytes[](5);
117

                            
                        
118
        actions[0] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS;
119
        params[0] = abi.encode(0);
120

                            
                        
121
        actions[1] = Actions.ASSERT_DELTA_EQUALS;
122
        params[1] = abi.encode(currency0, address(actionsRouter), 0);
123

                            
                        
124
        // Clear with 0.
125
        actions[2] = Actions.CLEAR;
126
        params[2] = abi.encode(currency0, 0, false, "");
127

                            
                        
128
        actions[3] = Actions.ASSERT_DELTA_EQUALS;
129
        params[3] = abi.encode(currency0, address(actionsRouter), 0);
130

                            
                        
131
        actions[4] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS;
132
        params[4] = abi.encode(0);
133

                            
                        
134
        actionsRouter.executeActions(actions, params);
135
    }
136

                            
                        
137
    function test_clear_reverts_zeroDelta_inputNonZero() external {
138
        uint256 amount = 1e18;
139
        Actions[] memory actions = new Actions[](3);
140
        bytes[] memory params = new bytes[](3);
141

                            
                        
142
        actions[0] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS;
143
        params[0] = abi.encode(0);
144

                            
                        
145
        actions[1] = Actions.ASSERT_DELTA_EQUALS;
146
        params[1] = abi.encode(currency0, address(actionsRouter), 0);
147

                            
                        
148
        // Clear with nonZero.
149
        actions[2] = Actions.CLEAR;
150
        params[2] = abi.encode(currency0, amount, false, "");
151

                            
                        
152
        vm.expectRevert(IPoolManager.MustClearExactPositiveDelta.selector);
153
        actionsRouter.executeActions(actions, params);
154
    }
155

                            
                        
156
    function test_clear_positiveDelta_inputExact_succeeds() external {
157
        uint256 amount = 1e18;
158
        Actions[] memory actions = new Actions[](8);
159
        bytes[] memory params = new bytes[](8);
160

                            
                        
161
        // Apply a positive delta.
162
        actions[0] = Actions.SYNC;
163
        params[0] = abi.encode(currency0);
164

                            
                        
165
        actions[1] = Actions.TRANSFER_FROM;
166
        params[1] = abi.encode(currency0, address(this), address(manager), amount);
167

                            
                        
168
        actions[2] = Actions.SETTLE;
169
        params[2] = abi.encode(currency0);
170

                            
                        
171
        // Delta should be equal to the positive amount.
172
        actions[3] = Actions.ASSERT_DELTA_EQUALS;
173
        params[3] = abi.encode(currency0, address(actionsRouter), amount);
174

                            
                        
175
        // Assert nonzero delta count is 1.
176
        actions[4] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS;
177
        params[4] = abi.encode(1);
178

                            
                        
179
        // Clear the exact delta amount.
180
        actions[5] = Actions.CLEAR;
181
        params[5] = abi.encode(currency0, amount, false, "");
182

                            
                        
183
        actions[6] = Actions.ASSERT_DELTA_EQUALS;
184
        params[6] = abi.encode(currency0, address(actionsRouter), 0);
185

                            
                        
186
        actions[7] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS;
187
        params[7] = abi.encode(0);
188

                            
                        
189
        actionsRouter.executeActions(actions, params);
190
    }
191

                            
                        
192
    function test_clear_gas() external {
193
        uint256 amount = 1e18;
194
        Actions[] memory actions = new Actions[](8);
195
        bytes[] memory params = new bytes[](8);
196

                            
                        
197
        // Apply a positive delta.
198
        actions[0] = Actions.SYNC;
199
        params[0] = abi.encode(currency0);
200

                            
                        
201
        actions[1] = Actions.TRANSFER_FROM;
202
        params[1] = abi.encode(currency0, address(this), address(manager), amount);
203

                            
                        
204
        actions[2] = Actions.SETTLE;
205
        params[2] = abi.encode(currency0);
206

                            
                        
207
        // Delta should be equal to the positive amount.
208
        actions[3] = Actions.ASSERT_DELTA_EQUALS;
209
        params[3] = abi.encode(currency0, address(actionsRouter), amount);
210

                            
                        
211
        // Assert nonzero delta count is 1.
212
        actions[4] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS;
213
        params[4] = abi.encode(1);
214

                            
                        
215
        // Clear the exact delta amount.
216
        actions[5] = Actions.CLEAR;
217
        params[5] = abi.encode(currency0, amount, true, "clear");
218

                            
                        
219
        actions[6] = Actions.ASSERT_DELTA_EQUALS;
220
        params[6] = abi.encode(currency0, address(actionsRouter), 0);
221

                            
                        
222
        actions[7] = Actions.ASSERT_NONZERO_DELTA_COUNT_EQUALS;
223
        params[7] = abi.encode(0);
224

                            
                        
225
        actionsRouter.executeActions(actions, params);
226
    }
227
}
228

                            
                        

Lines covered: 0 / 78 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import "forge-std/Test.sol";
5
import {V3Helper, IUniswapV3Pool, IUniswapV3MintCallback, IUniswapV3SwapCallback} from "./utils/V3Helper.sol";
6
import {Deployers} from "./utils/Deployers.sol";
7
import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
8
import {Fuzzers} from "../src/test/Fuzzers.sol";
9
import {IHooks} from "../src/interfaces/IHooks.sol";
10
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
11
import {BalanceDelta, BalanceDeltaLibrary, toBalanceDelta} from "../src/types/BalanceDelta.sol";
12
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
13
import {PoolKey} from "../src/types/PoolKey.sol";
14
import {SqrtPriceMath} from "../src/libraries/SqrtPriceMath.sol";
15
import {TickMath} from "../src/libraries/TickMath.sol";
16
import {SafeCast} from "../src/libraries/SafeCast.sol";
17
import {LiquidityAmounts} from "./utils/LiquidityAmounts.sol";
18

                            
                        
19
abstract contract V3Fuzzer is V3Helper, Deployers, Fuzzers, IUniswapV3MintCallback, IUniswapV3SwapCallback {
20
    using CurrencyLibrary for Currency;
21

                            
                        
22
    function setUp() public virtual override {
23
        super.setUp();
24
        deployFreshManagerAndRouters();
25
        deployMintAndApprove2Currencies();
26
    }
27

                            
                        
28
    function initPools(uint24 fee, int24 tickSpacing, int256 sqrtPriceX96seed)
29
        internal
30
        returns (IUniswapV3Pool v3Pool, PoolKey memory key_, uint160 sqrtPriceX96)
31
    {
32
        fee = uint24(bound(fee, 0, 999999));
33
        tickSpacing = int24(bound(tickSpacing, 1, 16383));
34
        // v3 pools don't allow overwriting existing fees, 500, 3000, 10000 are set by default in the constructor
35
        if (fee == 500) tickSpacing = 10;
36
        else if (fee == 3000) tickSpacing = 60;
37
        else if (fee == 10000) tickSpacing = 200;
38
        else v3Factory.enableFeeAmount(fee, tickSpacing);
39

                            
                        
40
        sqrtPriceX96 = createRandomSqrtPriceX96(tickSpacing, sqrtPriceX96seed);
41

                            
                        
42
        v3Pool = IUniswapV3Pool(v3Factory.createPool(Currency.unwrap(currency0), Currency.unwrap(currency1), fee));
43
        v3Pool.initialize(sqrtPriceX96);
44

                            
                        
45
        key_ = PoolKey(currency0, currency1, fee, tickSpacing, IHooks(address(0)));
46
        manager.initialize(key_, sqrtPriceX96, "");
47
    }
48

                            
                        
49
    function addLiquidity(
50
        IUniswapV3Pool v3Pool,
51
        PoolKey memory key_,
52
        uint160 sqrtPriceX96,
53
        int24 lowerTickUnsanitized,
54
        int24 upperTickUnsanitized,
55
        int256 liquidityDeltaUnbound,
56
        bool tight
57
    ) internal {
58
        IPoolManager.ModifyLiquidityParams memory v4LiquidityParams = IPoolManager.ModifyLiquidityParams({
59
            tickLower: lowerTickUnsanitized,
60
            tickUpper: upperTickUnsanitized,
61
            liquidityDelta: liquidityDeltaUnbound,
62
            salt: 0
63
        });
64

                            
                        
65
        v4LiquidityParams = tight
66
            ? createFuzzyLiquidityParamsWithTightBound(key_, v4LiquidityParams, sqrtPriceX96, 20)
67
            : createFuzzyLiquidityParams(key_, v4LiquidityParams, sqrtPriceX96);
68

                            
                        
69
        v3Pool.mint(
70
            address(this),
71
            v4LiquidityParams.tickLower,
72
            v4LiquidityParams.tickUpper,
73
            uint128(int128(v4LiquidityParams.liquidityDelta)),
74
            ""
75
        );
76

                            
                        
77
        modifyLiquidityRouter.modifyLiquidity(key_, v4LiquidityParams, "");
78
    }
79

                            
                        
80
    function swap(IUniswapV3Pool pool, PoolKey memory key_, bool zeroForOne, int128 amountSpecified)
81
        internal
82
        returns (int256 amount0Diff, int256 amount1Diff)
83
    {
84
        if (amountSpecified == 0) amountSpecified = 1;
85
        if (amountSpecified == type(int128).min) amountSpecified = type(int128).min + 1;
86
        // v3 swap
87
        (int256 amount0Delta, int256 amount1Delta) = pool.swap(
88
            // invert amountSpecified because v3 swaps use inverted signs
89
            address(this),
90
            zeroForOne,
91
            amountSpecified * -1,
92
            zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT,
93
            ""
94
        );
95
        // v3 can handle bigger numbers than v4, so if we exceed int128, check that the next call reverts
96
        bool overflows = false;
97
        if (
98
            amount0Delta > type(int128).max || amount1Delta > type(int128).max || amount0Delta < type(int128).min
99
                || amount1Delta < type(int128).min
100
        ) {
101
            overflows = true;
102
        }
103
        // v4 swap
104
        IPoolManager.SwapParams memory swapParams = IPoolManager.SwapParams({
105
            zeroForOne: zeroForOne,
106
            amountSpecified: amountSpecified,
107
            sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT
108
        });
109
        PoolSwapTest.TestSettings memory testSettings =
110
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
111

                            
                        
112
        BalanceDelta delta;
113
        try swapRouter.swap(key_, swapParams, testSettings, "") returns (BalanceDelta delta_) {
114
            delta = delta_;
115
        } catch (bytes memory reason) {
116
            require(overflows, "v4 should not overflow");
117
            assertEq(bytes4(reason), SafeCast.SafeCastOverflow.selector);
118
            delta = toBalanceDelta(0, 0);
119
            amount0Delta = 0;
120
            amount1Delta = 0;
121
        }
122

                            
                        
123
        // because signs for v3 and v4 swaps are inverted, add values up to get the difference
124
        amount0Diff = amount0Delta + delta.amount0();
125
        amount1Diff = amount1Delta + delta.amount1();
126
    }
127

                            
                        
128
    function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata) external {
129
        currency0.transfer(msg.sender, amount0Owed);
130
        currency1.transfer(msg.sender, amount1Owed);
131
    }
132

                            
                        
133
    function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata) external {
134
        if (amount0Delta > 0) currency0.transfer(msg.sender, uint256(amount0Delta));
135
        if (amount1Delta > 0) currency1.transfer(msg.sender, uint256(amount1Delta));
136
    }
137
}
138

                            
                        
139
contract V3SwapTests is V3Fuzzer {
140
    function test_shouldSwapEqual(
141
        uint24 feeSeed,
142
        int24 tickSpacingSeed,
143
        int24 lowerTickUnsanitized,
144
        int24 upperTickUnsanitized,
145
        int256 liquidityDeltaUnbound,
146
        int256 sqrtPriceX96seed,
147
        int128 swapAmount,
148
        bool zeroForOne
149
    ) public {
150
        (IUniswapV3Pool pool, PoolKey memory key_, uint160 sqrtPriceX96) =
151
            initPools(feeSeed, tickSpacingSeed, sqrtPriceX96seed);
152
        addLiquidity(pool, key_, sqrtPriceX96, lowerTickUnsanitized, upperTickUnsanitized, liquidityDeltaUnbound, false);
153
        (int256 amount0Diff, int256 amount1Diff) = swap(pool, key_, zeroForOne, swapAmount);
154
        assertEq(amount0Diff, 0);
155
        assertEq(amount1Diff, 0);
156
    }
157

                            
                        
158
    struct TightLiquidityParams {
159
        int24 lowerTickUnsanitized;
160
        int24 upperTickUnsanitized;
161
        int256 liquidityDeltaUnbound;
162
    }
163

                            
                        
164
    function test_shouldSwapEqualMultipleLP(
165
        uint24 feeSeed,
166
        int24 tickSpacingSeed,
167
        TightLiquidityParams[] memory liquidityParams,
168
        int256 sqrtPriceX96seed,
169
        int128 swapAmount,
170
        bool zeroForOne
171
    ) public {
172
        (IUniswapV3Pool pool, PoolKey memory key_, uint160 sqrtPriceX96) =
173
            initPools(feeSeed, tickSpacingSeed, sqrtPriceX96seed);
174
        for (uint256 i = 0; i < liquidityParams.length; ++i) {
175
            if (i == 20) break;
176
            addLiquidity(
177
                pool,
178
                key_,
179
                sqrtPriceX96,
180
                liquidityParams[i].lowerTickUnsanitized,
181
                liquidityParams[i].upperTickUnsanitized,
182
                liquidityParams[i].liquidityDeltaUnbound,
183
                true
184
            );
185
        }
186

                            
                        
187
        (int256 amount0Diff, int256 amount1Diff) = swap(pool, key_, zeroForOne, swapAmount);
188
        assertEq(amount0Diff, 0);
189
        assertEq(amount1Diff, 0);
190
    }
191
}
192

                            
                        

Lines covered: 0 / 540 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {IHooks} from "../src/interfaces/IHooks.sol";
6
import {Hooks} from "../src/libraries/Hooks.sol";
7
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
8
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
9
import {IProtocolFeeController} from "../src/interfaces/IProtocolFeeController.sol";
10
import {PoolManager} from "../src/PoolManager.sol";
11
import {TickMath} from "../src/libraries/TickMath.sol";
12
import {Pool} from "../src/libraries/Pool.sol";
13
import {Deployers} from "./utils/Deployers.sol";
14
import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
15
import {MockHooks} from "../src/test/MockHooks.sol";
16
import {MockContract} from "../src/test/MockContract.sol";
17
import {EmptyTestHooks} from "../src/test/EmptyTestHooks.sol";
18
import {PoolKey} from "../src/types/PoolKey.sol";
19
import {PoolModifyLiquidityTest} from "../src/test/PoolModifyLiquidityTest.sol";
20
import {BalanceDelta, BalanceDeltaLibrary} from "../src/types/BalanceDelta.sol";
21
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
22
import {PoolSettleTest} from "../src/test/PoolSettleTest.sol";
23
import {TestInvalidERC20} from "../src/test/TestInvalidERC20.sol";
24
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
25
import {PoolEmptyUnlockTest} from "../src/test/PoolEmptyUnlockTest.sol";
26
import {Action} from "../src/test/PoolNestedActionsTest.sol";
27
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
28
import {LPFeeLibrary} from "../src/libraries/LPFeeLibrary.sol";
29
import {Position} from "../src/libraries/Position.sol";
30
import {Constants} from "./utils/Constants.sol";
31
import {SafeCast} from "../src/libraries/SafeCast.sol";
32
// import {AmountHelpers} from "./utils/AmountHelpers.sol";
33
import {ProtocolFeeLibrary} from "../src/libraries/ProtocolFeeLibrary.sol";
34
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
35
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
36

                            
                        
37
contract PoolManagerTest is Test, Deployers, GasSnapshot {
38
    using Hooks for IHooks;
39
    using PoolIdLibrary for PoolKey;
40
    using LPFeeLibrary for uint24;
41
    using SafeCast for *;
42
    using ProtocolFeeLibrary for uint24;
43
    using StateLibrary for IPoolManager;
44

                            
                        
45
    event UnlockCallback();
46
    event ProtocolFeeControllerUpdated(address feeController);
47
    event ModifyLiquidity(
48
        PoolId indexed poolId, address indexed sender, int24 tickLower, int24 tickUpper, int256 liquidityDelta
49
    );
50
    event Swap(
51
        PoolId indexed poolId,
52
        address indexed sender,
53
        int128 amount0,
54
        int128 amount1,
55
        uint160 sqrtPriceX96,
56
        uint128 liquidity,
57
        int24 tick,
58
        uint24 fee
59
    );
60

                            
                        
61
    event Transfer(
62
        address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount
63
    );
64

                            
                        
65
    PoolEmptyUnlockTest emptyUnlockRouter;
66

                            
                        
67
    uint24 constant MAX_PROTOCOL_FEE_BOTH_TOKENS = (1000 << 12) | 1000; // 1000 1000
68

                            
                        
69
    function setUp() public {
70
        initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
71

                            
                        
72
        emptyUnlockRouter = new PoolEmptyUnlockTest(manager);
73
    }
74

                            
                        
75
    function test_bytecodeSize() public {
76
        snapSize("poolManager bytecode size", address(manager));
77
    }
78

                            
                        
79
    function test_addLiquidity_failsIfNotInitialized() public {
80
        vm.expectRevert(Pool.PoolNotInitialized.selector);
81
        modifyLiquidityRouter.modifyLiquidity(uninitializedKey, LIQUIDITY_PARAMS, ZERO_BYTES);
82
    }
83

                            
                        
84
    function test_addLiquidity_failsIfLocked() public {
85
        vm.expectRevert(IPoolManager.ManagerLocked.selector);
86
        manager.modifyLiquidity(uninitializedKey, LIQUIDITY_PARAMS, ZERO_BYTES);
87
    }
88

                            
                        
89
    function test_removeLiquidity_failsIfNotInitialized() public {
90
        vm.expectRevert(Pool.PoolNotInitialized.selector);
91
        modifyLiquidityRouter.modifyLiquidity(uninitializedKey, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
92
    }
93

                            
                        
94
    function test_removeLiquidity_failsIfLocked() public {
95
        vm.expectRevert(IPoolManager.ManagerLocked.selector);
96
        manager.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
97
    }
98

                            
                        
99
    function test_addLiquidity_succeedsIfInitialized(uint160 sqrtPriceX96) public {
100
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
101

                            
                        
102
        vm.expectEmit(true, true, true, true);
103
        emit ModifyLiquidity(
104
            key.toId(),
105
            address(modifyLiquidityRouter),
106
            LIQUIDITY_PARAMS.tickLower,
107
            LIQUIDITY_PARAMS.tickUpper,
108
            LIQUIDITY_PARAMS.liquidityDelta
109
        );
110

                            
                        
111
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
112
    }
113

                            
                        
114
    function test_removeLiquidity_succeedsIfInitialized(uint160 sqrtPriceX96) public {
115
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
116

                            
                        
117
        vm.expectEmit(true, true, true, true);
118
        emit ModifyLiquidity(
119
            key.toId(),
120
            address(modifyLiquidityRouter),
121
            REMOVE_LIQUIDITY_PARAMS.tickLower,
122
            REMOVE_LIQUIDITY_PARAMS.tickUpper,
123
            REMOVE_LIQUIDITY_PARAMS.liquidityDelta
124
        );
125

                            
                        
126
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
127
    }
128

                            
                        
129
    function test_addLiquidity_succeedsForNativeTokensIfInitialized(uint160 sqrtPriceX96) public {
130
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
131

                            
                        
132
        vm.expectEmit(true, true, true, true);
133
        emit ModifyLiquidity(
134
            nativeKey.toId(),
135
            address(modifyLiquidityRouter),
136
            LIQUIDITY_PARAMS.tickLower,
137
            LIQUIDITY_PARAMS.tickUpper,
138
            LIQUIDITY_PARAMS.liquidityDelta
139
        );
140

                            
                        
141
        modifyLiquidityRouter.modifyLiquidity{value: 1 ether}(nativeKey, LIQUIDITY_PARAMS, ZERO_BYTES);
142
    }
143

                            
                        
144
    function test_removeLiquidity_succeedsForNativeTokensIfInitialized(uint160 sqrtPriceX96) public {
145
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
146

                            
                        
147
        vm.expectEmit(true, true, true, true);
148
        emit ModifyLiquidity(
149
            nativeKey.toId(),
150
            address(modifyLiquidityRouter),
151
            REMOVE_LIQUIDITY_PARAMS.tickLower,
152
            REMOVE_LIQUIDITY_PARAMS.tickUpper,
153
            REMOVE_LIQUIDITY_PARAMS.liquidityDelta
154
        );
155

                            
                        
156
        modifyLiquidityRouter.modifyLiquidity{value: 1 ether}(nativeKey, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
157
    }
158

                            
                        
159
    function test_addLiquidity_succeedsWithHooksIfInitialized(uint160 sqrtPriceX96) public {
160
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
161

                            
                        
162
        address payable mockAddr =
163
            payable(address(uint160(Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG)));
164
        address payable hookAddr = payable(Constants.ALL_HOOKS);
165

                            
                        
166
        vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
167
        MockContract mockContract = new MockContract();
168
        vm.etch(mockAddr, address(mockContract).code);
169

                            
                        
170
        MockContract(mockAddr).setImplementation(hookAddr);
171

                            
                        
172
        (key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96, ZERO_BYTES);
173

                            
                        
174
        BalanceDelta balanceDelta = modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
175

                            
                        
176
        bytes32 beforeSelector = MockHooks.beforeAddLiquidity.selector;
177
        bytes memory beforeParams = abi.encode(address(modifyLiquidityRouter), key, LIQUIDITY_PARAMS, ZERO_BYTES);
178
        bytes32 afterSelector = MockHooks.afterAddLiquidity.selector;
179
        bytes memory afterParams =
180
            abi.encode(address(modifyLiquidityRouter), key, LIQUIDITY_PARAMS, balanceDelta, ZERO_BYTES);
181

                            
                        
182
        assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1);
183
        assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams));
184
        assertEq(MockContract(mockAddr).timesCalledSelector(afterSelector), 1);
185
        assertTrue(MockContract(mockAddr).calledWithSelector(afterSelector, afterParams));
186
    }
187

                            
                        
188
    function test_removeLiquidity_succeedsWithHooksIfInitialized(uint160 sqrtPriceX96) public {
189
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
190

                            
                        
191
        address payable mockAddr =
192
            payable(address(uint160(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)));
193
        address payable hookAddr = payable(Constants.ALL_HOOKS);
194

                            
                        
195
        vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
196
        MockContract mockContract = new MockContract();
197
        vm.etch(mockAddr, address(mockContract).code);
198

                            
                        
199
        MockContract(mockAddr).setImplementation(hookAddr);
200

                            
                        
201
        (key,) = initPool(currency0, currency1, IHooks(mockAddr), 3000, sqrtPriceX96, ZERO_BYTES);
202
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
203
        BalanceDelta balanceDelta = modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
204

                            
                        
205
        bytes32 beforeSelector = MockHooks.beforeRemoveLiquidity.selector;
206
        bytes memory beforeParams = abi.encode(address(modifyLiquidityRouter), key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
207
        bytes32 afterSelector = MockHooks.afterRemoveLiquidity.selector;
208
        bytes memory afterParams =
209
            abi.encode(address(modifyLiquidityRouter), key, REMOVE_LIQUIDITY_PARAMS, balanceDelta, ZERO_BYTES);
210

                            
                        
211
        assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1);
212
        assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams));
213
        assertEq(MockContract(mockAddr).timesCalledSelector(afterSelector), 1);
214
        assertTrue(MockContract(mockAddr).calledWithSelector(afterSelector, afterParams));
215
    }
216

                            
                        
217
    function test_addLiquidity_failsWithIncorrectSelectors() public {
218
        address hookAddr = address(uint160(Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG));
219

                            
                        
220
        MockHooks impl = new MockHooks();
221
        vm.etch(hookAddr, address(impl).code);
222
        MockHooks mockHooks = MockHooks(hookAddr);
223

                            
                        
224
        (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES);
225

                            
                        
226
        mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, bytes4(0xdeadbeef));
227
        mockHooks.setReturnValue(mockHooks.afterAddLiquidity.selector, bytes4(0xdeadbeef));
228

                            
                        
229
        // Fails at beforeAddLiquidity hook.
230
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
231
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
232

                            
                        
233
        // Fail at afterAddLiquidity hook.
234
        mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, mockHooks.beforeAddLiquidity.selector);
235
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
236
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
237
    }
238

                            
                        
239
    function test_removeLiquidity_failsWithIncorrectSelectors() public {
240
        address hookAddr = address(uint160(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
241

                            
                        
242
        MockHooks impl = new MockHooks();
243
        vm.etch(hookAddr, address(impl).code);
244
        MockHooks mockHooks = MockHooks(hookAddr);
245

                            
                        
246
        (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES);
247
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
248

                            
                        
249
        mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, bytes4(0xdeadbeef));
250
        mockHooks.setReturnValue(mockHooks.afterRemoveLiquidity.selector, bytes4(0xdeadbeef));
251

                            
                        
252
        // Fails at beforeRemoveLiquidity hook.
253
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
254
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
255

                            
                        
256
        // Fail at afterRemoveLiquidity hook.
257
        mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, mockHooks.beforeRemoveLiquidity.selector);
258
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
259
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
260
    }
261

                            
                        
262
    function test_addLiquidity_succeedsWithCorrectSelectors() public {
263
        address hookAddr = address(uint160(Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG));
264

                            
                        
265
        MockHooks impl = new MockHooks();
266
        vm.etch(hookAddr, address(impl).code);
267
        MockHooks mockHooks = MockHooks(hookAddr);
268

                            
                        
269
        (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES);
270

                            
                        
271
        mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, mockHooks.beforeAddLiquidity.selector);
272
        mockHooks.setReturnValue(mockHooks.afterAddLiquidity.selector, mockHooks.afterAddLiquidity.selector);
273

                            
                        
274
        vm.expectEmit(true, true, true, true);
275
        emit ModifyLiquidity(
276
            key.toId(),
277
            address(modifyLiquidityRouter),
278
            LIQUIDITY_PARAMS.tickLower,
279
            LIQUIDITY_PARAMS.tickUpper,
280
            LIQUIDITY_PARAMS.liquidityDelta
281
        );
282

                            
                        
283
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
284
    }
285

                            
                        
286
    function test_removeLiquidity_succeedsWithCorrectSelectors() public {
287
        address hookAddr = address(uint160(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
288

                            
                        
289
        MockHooks impl = new MockHooks();
290
        vm.etch(hookAddr, address(impl).code);
291
        MockHooks mockHooks = MockHooks(hookAddr);
292

                            
                        
293
        (key,) = initPool(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES);
294
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
295

                            
                        
296
        mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, mockHooks.beforeRemoveLiquidity.selector);
297
        mockHooks.setReturnValue(mockHooks.afterRemoveLiquidity.selector, mockHooks.afterRemoveLiquidity.selector);
298

                            
                        
299
        vm.expectEmit(true, true, true, true);
300
        emit ModifyLiquidity(
301
            key.toId(),
302
            address(modifyLiquidityRouter),
303
            REMOVE_LIQUIDITY_PARAMS.tickLower,
304
            REMOVE_LIQUIDITY_PARAMS.tickUpper,
305
            REMOVE_LIQUIDITY_PARAMS.liquidityDelta
306
        );
307

                            
                        
308
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
309
    }
310

                            
                        
311
    function test_addLiquidity_6909() public {
312
        // convert test tokens into ERC6909 claims
313
        claimsRouter.deposit(currency0, address(this), 10_000e18);
314
        claimsRouter.deposit(currency1, address(this), 10_000e18);
315
        assertEq(manager.balanceOf(address(this), currency0.toId()), 10_000e18);
316
        assertEq(manager.balanceOf(address(this), currency1.toId()), 10_000e18);
317

                            
                        
318
        uint256 currency0BalanceBefore = currency0.balanceOfSelf();
319
        uint256 currency1BalanceBefore = currency1.balanceOfSelf();
320
        uint256 currency0PMBalanceBefore = currency0.balanceOf(address(manager));
321
        uint256 currency1PMBalanceBefore = currency1.balanceOf(address(manager));
322

                            
                        
323
        // allow liquidity router to burn our 6909 tokens
324
        manager.setOperator(address(modifyLiquidityRouter), true);
325

                            
                        
326
        // add liquidity with 6909: settleUsingBurn=true, takeClaims=true (unused)
327
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES, true, true);
328

                            
                        
329
        assertLt(manager.balanceOf(address(this), currency0.toId()), 10_000e18);
330
        assertLt(manager.balanceOf(address(this), currency1.toId()), 10_000e18);
331

                            
                        
332
        // ERC20s are unspent
333
        assertEq(currency0.balanceOfSelf(), currency0BalanceBefore);
334
        assertEq(currency1.balanceOfSelf(), currency1BalanceBefore);
335

                            
                        
336
        // PoolManager did not receive net-new ERC20s
337
        assertEq(currency0.balanceOf(address(manager)), currency0PMBalanceBefore);
338
        assertEq(currency1.balanceOf(address(manager)), currency1PMBalanceBefore);
339
    }
340

                            
                        
341
    function test_removeLiquidity_6909() public {
342
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
343

                            
                        
344
        assertEq(manager.balanceOf(address(this), currency0.toId()), 0);
345
        assertEq(manager.balanceOf(address(this), currency1.toId()), 0);
346

                            
                        
347
        uint256 currency0BalanceBefore = currency0.balanceOfSelf();
348
        uint256 currency1BalanceBefore = currency1.balanceOfSelf();
349
        uint256 currency0PMBalanceBefore = currency0.balanceOf(address(manager));
350
        uint256 currency1PMBalanceBefore = currency1.balanceOf(address(manager));
351

                            
                        
352
        // remove liquidity as 6909: settleUsingBurn=true (unused), takeClaims=true
353
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES, true, true);
354

                            
                        
355
        assertTrue(manager.balanceOf(address(this), currency0.toId()) > 0);
356
        assertTrue(manager.balanceOf(address(this), currency1.toId()) > 0);
357

                            
                        
358
        // ERC20s are unspent
359
        assertEq(currency0.balanceOfSelf(), currency0BalanceBefore);
360
        assertEq(currency1.balanceOfSelf(), currency1BalanceBefore);
361

                            
                        
362
        // PoolManager did lose ERC-20s
363
        assertEq(currency0.balanceOf(address(manager)), currency0PMBalanceBefore);
364
        assertEq(currency1.balanceOf(address(manager)), currency1PMBalanceBefore);
365
    }
366

                            
                        
367
    function test_addLiquidity_gas() public {
368
        IPoolManager.ModifyLiquidityParams memory uniqueParams =
369
            IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
370
        modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
371
        snapLastCall("simple addLiquidity");
372
    }
373

                            
                        
374
    function test_addLiquidity_secondAdditionSameRange_gas() public {
375
        IPoolManager.ModifyLiquidityParams memory uniqueParams =
376
            IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
377
        modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
378
        modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
379
        snapLastCall("simple addLiquidity second addition same range");
380
    }
381

                            
                        
382
    function test_removeLiquidity_gas() public {
383
        IPoolManager.ModifyLiquidityParams memory uniqueParams =
384
            IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
385
        // add some liquidity to remove
386
        modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
387

                            
                        
388
        uniqueParams.liquidityDelta *= -1;
389
        modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
390
        snapLastCall("simple removeLiquidity");
391
    }
392

                            
                        
393
    function test_removeLiquidity_someLiquidityRemains_gas() public {
394
        // add double the liquidity to remove
395
        IPoolManager.ModifyLiquidityParams memory uniqueParams =
396
            IPoolManager.ModifyLiquidityParams({tickLower: -300, tickUpper: -180, liquidityDelta: 1e18, salt: 0});
397
        modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
398

                            
                        
399
        uniqueParams.liquidityDelta /= -2;
400
        modifyLiquidityNoChecks.modifyLiquidity(key, uniqueParams, ZERO_BYTES);
401
        snapLastCall("simple removeLiquidity some liquidity remains");
402
    }
403

                            
                        
404
    function test_addLiquidity_succeeds() public {
405
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
406
    }
407

                            
                        
408
    function test_removeLiquidity_succeeds() public {
409
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
410
    }
411

                            
                        
412
    function test_addLiquidity_withNative_gas() public {
413
        modifyLiquidityRouter.modifyLiquidity{value: 1 ether}(nativeKey, LIQUIDITY_PARAMS, ZERO_BYTES);
414
        snapLastCall("addLiquidity with native token");
415
    }
416

                            
                        
417
    function test_removeLiquidity_withNative_gas() public {
418
        modifyLiquidityRouter.modifyLiquidity{value: 1 ether}(nativeKey, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
419
        snapLastCall("removeLiquidity with native token");
420
    }
421

                            
                        
422
    function test_addLiquidity_withHooks_gas() public {
423
        address allHooksAddr = Constants.ALL_HOOKS;
424
        MockHooks impl = new MockHooks();
425
        vm.etch(allHooksAddr, address(impl).code);
426
        MockHooks mockHooks = MockHooks(allHooksAddr);
427

                            
                        
428
        (key,) = initPool(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES);
429

                            
                        
430
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
431
        snapLastCall("addLiquidity with empty hook");
432
    }
433

                            
                        
434
    function test_removeLiquidity_withHooks_gas() public {
435
        address allHooksAddr = Constants.ALL_HOOKS;
436
        MockHooks impl = new MockHooks();
437
        vm.etch(allHooksAddr, address(impl).code);
438
        MockHooks mockHooks = MockHooks(allHooksAddr);
439

                            
                        
440
        (key,) = initPool(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES);
441
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
442

                            
                        
443
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
444
        snapLastCall("removeLiquidity with empty hook");
445
    }
446

                            
                        
447
    function test_swap_failsIfNotInitialized(uint160 sqrtPriceX96) public {
448
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
449

                            
                        
450
        key.fee = 100;
451
        IPoolManager.SwapParams memory params =
452
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: sqrtPriceX96});
453

                            
                        
454
        PoolSwapTest.TestSettings memory testSettings =
455
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
456

                            
                        
457
        vm.expectRevert(Pool.PoolNotInitialized.selector);
458
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
459
    }
460

                            
                        
461
    function test_swap_succeedsIfInitialized() public {
462
        PoolSwapTest.TestSettings memory testSettings =
463
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
464

                            
                        
465
        vm.expectEmit(true, true, true, true);
466
        emit Swap(
467
            key.toId(), address(swapRouter), int128(-100), int128(98), 79228162514264329749955861424, 1e18, -1, 3000
468
        );
469

                            
                        
470
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
471
    }
472

                            
                        
473
    function test_swap_failsIfLocked() public {
474
        vm.expectRevert(IPoolManager.ManagerLocked.selector);
475
        manager.swap(key, SWAP_PARAMS, ZERO_BYTES);
476
    }
477

                            
                        
478
    function test_swap_succeedsWithNativeTokensIfInitialized() public {
479
        PoolSwapTest.TestSettings memory testSettings =
480
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
481

                            
                        
482
        vm.expectEmit(true, true, true, true);
483
        emit Swap(
484
            nativeKey.toId(),
485
            address(swapRouter),
486
            int128(-100),
487
            int128(98),
488
            79228162514264329749955861424,
489
            1e18,
490
            -1,
491
            3000
492
        );
493

                            
                        
494
        swapRouter.swap{value: 100}(nativeKey, SWAP_PARAMS, testSettings, ZERO_BYTES);
495
    }
496

                            
                        
497
    function test_swap_succeedsWithHooksIfInitialized() public {
498
        address payable mockAddr = payable(address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG)));
499
        address payable hookAddr = payable(Constants.ALL_HOOKS);
500

                            
                        
501
        vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
502
        MockContract mockContract = new MockContract();
503
        vm.etch(mockAddr, address(mockContract).code);
504

                            
                        
505
        MockContract(mockAddr).setImplementation(hookAddr);
506

                            
                        
507
        (key,) = initPoolAndAddLiquidity(currency0, currency1, IHooks(mockAddr), 3000, SQRT_PRICE_1_1, ZERO_BYTES);
508

                            
                        
509
        PoolSwapTest.TestSettings memory testSettings =
510
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
511

                            
                        
512
        BalanceDelta balanceDelta = swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
513

                            
                        
514
        bytes32 beforeSelector = MockHooks.beforeSwap.selector;
515
        bytes memory beforeParams = abi.encode(address(swapRouter), key, SWAP_PARAMS, ZERO_BYTES);
516

                            
                        
517
        bytes32 afterSelector = MockHooks.afterSwap.selector;
518
        bytes memory afterParams = abi.encode(address(swapRouter), key, SWAP_PARAMS, balanceDelta, ZERO_BYTES);
519

                            
                        
520
        assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1);
521
        assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams));
522
        assertEq(MockContract(mockAddr).timesCalledSelector(afterSelector), 1);
523
        assertTrue(MockContract(mockAddr).calledWithSelector(afterSelector, afterParams));
524
    }
525

                            
                        
526
    function test_swap_failsWithIncorrectSelectors() public {
527
        address hookAddr = address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG));
528

                            
                        
529
        MockHooks impl = new MockHooks();
530
        vm.etch(hookAddr, address(impl).code);
531
        MockHooks mockHooks = MockHooks(hookAddr);
532

                            
                        
533
        (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES);
534

                            
                        
535
        IPoolManager.SwapParams memory swapParams =
536
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 10, sqrtPriceLimitX96: SQRT_PRICE_1_2});
537

                            
                        
538
        PoolSwapTest.TestSettings memory testSettings =
539
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
540

                            
                        
541
        mockHooks.setReturnValue(mockHooks.beforeSwap.selector, bytes4(0xdeadbeef));
542
        mockHooks.setReturnValue(mockHooks.afterSwap.selector, bytes4(0xdeadbeef));
543

                            
                        
544
        // Fails at beforeSwap hook.
545
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
546
        swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES);
547

                            
                        
548
        // Fail at afterSwap hook.
549
        mockHooks.setReturnValue(mockHooks.beforeSwap.selector, mockHooks.beforeSwap.selector);
550
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
551
        swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES);
552
    }
553

                            
                        
554
    function test_swap_succeedsWithCorrectSelectors() public {
555
        address hookAddr = address(uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG));
556

                            
                        
557
        MockHooks impl = new MockHooks();
558
        vm.etch(hookAddr, address(impl).code);
559
        MockHooks mockHooks = MockHooks(hookAddr);
560

                            
                        
561
        (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES);
562

                            
                        
563
        IPoolManager.SwapParams memory swapParams =
564
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -10, sqrtPriceLimitX96: SQRT_PRICE_1_2});
565

                            
                        
566
        PoolSwapTest.TestSettings memory testSettings =
567
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
568

                            
                        
569
        mockHooks.setReturnValue(mockHooks.beforeSwap.selector, mockHooks.beforeSwap.selector);
570
        mockHooks.setReturnValue(mockHooks.afterSwap.selector, mockHooks.afterSwap.selector);
571

                            
                        
572
        vm.expectEmit(true, true, true, true);
573
        emit Swap(key.toId(), address(swapRouter), -10, 8, 79228162514264336880490487708, 1e18, -1, 100);
574

                            
                        
575
        swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES);
576
    }
577

                            
                        
578
    function test_swap_succeeds() public {
579
        PoolSwapTest.TestSettings memory testSettings =
580
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
581

                            
                        
582
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
583
    }
584

                            
                        
585
    function test_swap_gas() public {
586
        swapRouterNoChecks.swap(key, SWAP_PARAMS);
587
        snapLastCall("simple swap");
588
    }
589

                            
                        
590
    function test_swap_withNative_succeeds() public {
591
        PoolSwapTest.TestSettings memory testSettings =
592
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
593

                            
                        
594
        swapRouter.swap{value: 100}(nativeKey, SWAP_PARAMS, testSettings, ZERO_BYTES);
595
    }
596

                            
                        
597
    function test_swap_withNative_gas() public {
598
        swapRouterNoChecks.swap{value: 100}(nativeKey, SWAP_PARAMS);
599
        snapLastCall("simple swap with native");
600
    }
601

                            
                        
602
    function test_swap_withHooks_gas() public {
603
        address allHooksAddr = Constants.ALL_HOOKS;
604

                            
                        
605
        MockHooks impl = new MockHooks();
606
        vm.etch(allHooksAddr, address(impl).code);
607
        MockHooks mockHooks = MockHooks(allHooksAddr);
608

                            
                        
609
        (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES);
610

                            
                        
611
        PoolSwapTest.TestSettings memory testSettings =
612
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
613

                            
                        
614
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
615

                            
                        
616
        IPoolManager.SwapParams memory swapParams =
617
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_1_4});
618
        testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
619

                            
                        
620
        swapRouter.swap(key, swapParams, testSettings, ZERO_BYTES);
621
        snapLastCall("swap with hooks");
622
    }
623

                            
                        
624
    function test_swap_mint6909IfOutputNotTaken_gas() public {
625
        PoolSwapTest.TestSettings memory testSettings =
626
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
627

                            
                        
628
        vm.expectEmit();
629
        emit Transfer(address(swapRouter), address(0), address(this), CurrencyLibrary.toId(currency1), 98);
630
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
631
        snapLastCall("swap mint output as 6909");
632

                            
                        
633
        uint256 erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(currency1));
634
        assertEq(erc6909Balance, 98);
635
    }
636

                            
                        
637
    function test_swap_mint6909IfNativeOutputNotTaken_gas() public {
638
        IPoolManager.SwapParams memory params =
639
            IPoolManager.SwapParams({zeroForOne: false, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_2_1});
640

                            
                        
641
        PoolSwapTest.TestSettings memory testSettings =
642
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
643

                            
                        
644
        vm.expectEmit();
645
        emit Transfer(address(swapRouter), address(0), address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE), 98);
646
        swapRouter.swap(nativeKey, params, testSettings, ZERO_BYTES);
647
        snapLastCall("swap mint native output as 6909");
648

                            
                        
649
        uint256 erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE));
650
        assertEq(erc6909Balance, 98);
651
    }
652

                            
                        
653
    function test_swap_burn6909AsInput_gas() public {
654
        PoolSwapTest.TestSettings memory testSettings =
655
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
656

                            
                        
657
        vm.expectEmit();
658
        emit Transfer(address(swapRouter), address(0), address(this), CurrencyLibrary.toId(currency1), 98);
659
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
660

                            
                        
661
        uint256 erc6909Balance = manager.balanceOf(address(this), uint256(uint160(Currency.unwrap(currency1))));
662
        assertEq(erc6909Balance, 98);
663

                            
                        
664
        // give permission for swapRouter to burn the 6909s
665
        manager.setOperator(address(swapRouter), true);
666

                            
                        
667
        // swap from currency1 to currency0 again, using 6909s as input tokens
668
        IPoolManager.SwapParams memory params =
669
            IPoolManager.SwapParams({zeroForOne: false, amountSpecified: 25, sqrtPriceLimitX96: SQRT_PRICE_4_1});
670
        testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: true});
671

                            
                        
672
        vm.expectEmit();
673
        emit Transfer(address(swapRouter), address(this), address(0), CurrencyLibrary.toId(currency1), 27);
674
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
675
        snapLastCall("swap burn 6909 for input");
676

                            
                        
677
        erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(currency1));
678
        assertEq(erc6909Balance, 71);
679
    }
680

                            
                        
681
    function test_swap_burnNative6909AsInput_gas() public {
682
        IPoolManager.SwapParams memory params =
683
            IPoolManager.SwapParams({zeroForOne: false, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_2_1});
684

                            
                        
685
        PoolSwapTest.TestSettings memory testSettings =
686
            PoolSwapTest.TestSettings({takeClaims: true, settleUsingBurn: false});
687

                            
                        
688
        vm.expectEmit();
689
        emit Transfer(address(swapRouter), address(0), address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE), 98);
690
        swapRouter.swap(nativeKey, params, testSettings, ZERO_BYTES);
691

                            
                        
692
        uint256 erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE));
693
        assertEq(erc6909Balance, 98);
694

                            
                        
695
        // give permission for swapRouter to burn the 6909s
696
        manager.setOperator(address(swapRouter), true);
697

                            
                        
698
        // swap from currency0 to currency1, using 6909s as input tokens
699
        params = IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 25, sqrtPriceLimitX96: SQRT_PRICE_1_4});
700
        testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: true});
701

                            
                        
702
        vm.expectEmit();
703
        emit Transfer(address(swapRouter), address(this), address(0), CurrencyLibrary.toId(CurrencyLibrary.NATIVE), 27);
704
        // don't have to send in native currency since burning 6909 for input
705
        swapRouter.swap(nativeKey, params, testSettings, ZERO_BYTES);
706
        snapLastCall("swap burn native 6909 for input");
707

                            
                        
708
        erc6909Balance = manager.balanceOf(address(this), CurrencyLibrary.toId(CurrencyLibrary.NATIVE));
709
        assertEq(erc6909Balance, 71);
710
    }
711

                            
                        
712
    function test_swap_againstLiquidity_gas() public {
713
        PoolSwapTest.TestSettings memory testSettings =
714
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
715

                            
                        
716
        swapRouter.swap(key, SWAP_PARAMS, testSettings, ZERO_BYTES);
717

                            
                        
718
        IPoolManager.SwapParams memory params =
719
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_1_4});
720

                            
                        
721
        swapRouter.swap(key, params, testSettings, ZERO_BYTES);
722
        snapLastCall("swap against liquidity");
723
    }
724

                            
                        
725
    function test_swap_againstLiqWithNative_gas() public {
726
        PoolSwapTest.TestSettings memory testSettings =
727
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
728

                            
                        
729
        swapRouter.swap{value: 1 ether}(nativeKey, SWAP_PARAMS, testSettings, ZERO_BYTES);
730

                            
                        
731
        IPoolManager.SwapParams memory params =
732
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_1_4});
733

                            
                        
734
        swapRouter.swap{value: 1 ether}(nativeKey, params, testSettings, ZERO_BYTES);
735
        snapLastCall("swap against liquidity with native token");
736
    }
737

                            
                        
738
    function test_swap_accruesProtocolFees(uint16 protocolFee0, uint16 protocolFee1, int256 amountSpecified) public {
739
        protocolFee0 = uint16(bound(protocolFee0, 0, 1000));
740
        protocolFee1 = uint16(bound(protocolFee1, 0, 1000));
741
        vm.assume(amountSpecified != 0);
742

                            
                        
743
        uint24 protocolFee = (uint24(protocolFee1) << 12) | uint24(protocolFee0);
744

                            
                        
745
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(key.toId());
746
        assertEq(slot0ProtocolFee, 0);
747

                            
                        
748
        vm.prank(address(feeController));
749
        manager.setProtocolFee(key, protocolFee);
750

                            
                        
751
        (,, slot0ProtocolFee,) = manager.getSlot0(key.toId());
752
        assertEq(slot0ProtocolFee, protocolFee);
753

                            
                        
754
        // Add liquidity - Fees dont accrue for positive liquidity delta.
755
        IPoolManager.ModifyLiquidityParams memory params = LIQUIDITY_PARAMS;
756
        modifyLiquidityRouter.modifyLiquidity(key, params, ZERO_BYTES);
757

                            
                        
758
        assertEq(manager.protocolFeesAccrued(currency0), 0);
759
        assertEq(manager.protocolFeesAccrued(currency1), 0);
760

                            
                        
761
        // Remove liquidity - Fees dont accrue for negative liquidity delta.
762
        params.liquidityDelta = -LIQUIDITY_PARAMS.liquidityDelta;
763
        modifyLiquidityRouter.modifyLiquidity(key, params, ZERO_BYTES);
764

                            
                        
765
        assertEq(manager.protocolFeesAccrued(currency0), 0);
766
        assertEq(manager.protocolFeesAccrued(currency1), 0);
767

                            
                        
768
        // Now re-add the liquidity to test swap
769
        params.liquidityDelta = LIQUIDITY_PARAMS.liquidityDelta;
770
        modifyLiquidityRouter.modifyLiquidity(key, params, ZERO_BYTES);
771

                            
                        
772
        IPoolManager.SwapParams memory swapParams =
773
            IPoolManager.SwapParams(false, amountSpecified, TickMath.MAX_SQRT_PRICE - 1);
774
        BalanceDelta delta = swapRouter.swap(key, swapParams, PoolSwapTest.TestSettings(false, false), ZERO_BYTES);
775
        uint256 expectedProtocolFee =
776
            uint256(uint128(-delta.amount1())) * protocolFee1 / ProtocolFeeLibrary.PIPS_DENOMINATOR;
777
        assertEq(manager.protocolFeesAccrued(currency0), 0);
778
        assertEq(manager.protocolFeesAccrued(currency1), expectedProtocolFee);
779
    }
780

                            
                        
781
    function test_donate_failsIfNotInitialized() public {
782
        vm.expectRevert(Pool.PoolNotInitialized.selector);
783
        donateRouter.donate(uninitializedKey, 100, 100, ZERO_BYTES);
784
    }
785

                            
                        
786
    function test_donate_failsIfLocked() public {
787
        vm.expectRevert(IPoolManager.ManagerLocked.selector);
788
        manager.donate(key, 100, 100, ZERO_BYTES);
789
    }
790

                            
                        
791
    function test_donate_failsIfNoLiquidity(uint160 sqrtPriceX96) public {
792
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
793

                            
                        
794
        (key,) = initPool(currency0, currency1, IHooks(address(0)), 100, sqrtPriceX96, ZERO_BYTES);
795

                            
                        
796
        vm.expectRevert(Pool.NoLiquidityToReceiveFees.selector);
797
        donateRouter.donate(key, 100, 100, ZERO_BYTES);
798
    }
799

                            
                        
800
    // test successful donation if pool has liquidity
801
    function test_donate_succeedsWhenPoolHasLiquidity() public {
802
        (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(key.toId());
803
        assertEq(feeGrowthGlobal0X128, 0);
804
        assertEq(feeGrowthGlobal1X128, 0);
805

                            
                        
806
        donateRouter.donate(key, 100, 200, ZERO_BYTES);
807
        snapLastCall("donate gas with 2 tokens");
808

                            
                        
809
        (feeGrowthGlobal0X128, feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(key.toId());
810
        assertEq(feeGrowthGlobal0X128, 34028236692093846346337);
811
        assertEq(feeGrowthGlobal1X128, 68056473384187692692674);
812
    }
813

                            
                        
814
    function test_donate_succeedsForNativeTokensWhenPoolHasLiquidity() public {
815
        (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(nativeKey.toId());
816
        assertEq(feeGrowthGlobal0X128, 0);
817
        assertEq(feeGrowthGlobal1X128, 0);
818

                            
                        
819
        donateRouter.donate{value: 100}(nativeKey, 100, 200, ZERO_BYTES);
820

                            
                        
821
        (feeGrowthGlobal0X128, feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(nativeKey.toId());
822
        assertEq(feeGrowthGlobal0X128, 34028236692093846346337);
823
        assertEq(feeGrowthGlobal1X128, 68056473384187692692674);
824
    }
825

                            
                        
826
    function test_donate_failsWithIncorrectSelectors() public {
827
        address hookAddr = address(uint160(Hooks.BEFORE_DONATE_FLAG | Hooks.AFTER_DONATE_FLAG));
828

                            
                        
829
        MockHooks impl = new MockHooks();
830
        vm.etch(hookAddr, address(impl).code);
831
        MockHooks mockHooks = MockHooks(hookAddr);
832

                            
                        
833
        (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES);
834

                            
                        
835
        mockHooks.setReturnValue(mockHooks.beforeDonate.selector, bytes4(0xdeadbeef));
836
        mockHooks.setReturnValue(mockHooks.afterDonate.selector, bytes4(0xdeadbeef));
837

                            
                        
838
        // Fails at beforeDonate hook.
839
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
840
        donateRouter.donate(key, 100, 200, ZERO_BYTES);
841

                            
                        
842
        // Fail at afterDonate hook.
843
        mockHooks.setReturnValue(mockHooks.beforeDonate.selector, mockHooks.beforeDonate.selector);
844
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
845
        donateRouter.donate(key, 100, 200, ZERO_BYTES);
846
    }
847

                            
                        
848
    function test_donate_succeedsWithCorrectSelectors() public {
849
        address hookAddr = address(uint160(Hooks.BEFORE_DONATE_FLAG | Hooks.AFTER_DONATE_FLAG));
850

                            
                        
851
        MockHooks impl = new MockHooks();
852
        vm.etch(hookAddr, address(impl).code);
853
        MockHooks mockHooks = MockHooks(hookAddr);
854

                            
                        
855
        (key,) = initPoolAndAddLiquidity(currency0, currency1, mockHooks, 100, SQRT_PRICE_1_1, ZERO_BYTES);
856

                            
                        
857
        mockHooks.setReturnValue(mockHooks.beforeDonate.selector, mockHooks.beforeDonate.selector);
858
        mockHooks.setReturnValue(mockHooks.afterDonate.selector, mockHooks.afterDonate.selector);
859

                            
                        
860
        donateRouter.donate(key, 100, 200, ZERO_BYTES);
861
    }
862

                            
                        
863
    function test_donate_OneToken_gas() public {
864
        donateRouter.donate(key, 100, 0, ZERO_BYTES);
865
        snapLastCall("donate gas with 1 token");
866
    }
867

                            
                        
868
    function test_take_failsWithNoLiquidity() public {
869
        deployFreshManagerAndRouters();
870

                            
                        
871
        vm.expectRevert();
872
        takeRouter.take(key, 100, 0);
873
    }
874

                            
                        
875
    function test_take_failsWithInvalidTokensThatDoNotReturnTrueOnTransfer() public {
876
        TestInvalidERC20 invalidToken = new TestInvalidERC20(2 ** 255);
877
        Currency invalidCurrency = Currency.wrap(address(invalidToken));
878
        invalidToken.approve(address(modifyLiquidityRouter), type(uint256).max);
879
        invalidToken.approve(address(takeRouter), type(uint256).max);
880

                            
                        
881
        bool currency0Invalid = invalidCurrency < currency0;
882

                            
                        
883
        (key,) = initPoolAndAddLiquidity(
884
            (currency0Invalid ? invalidCurrency : currency0),
885
            (currency0Invalid ? currency0 : invalidCurrency),
886
            IHooks(address(0)),
887
            3000,
888
            SQRT_PRICE_1_1,
889
            ZERO_BYTES
890
        );
891

                            
                        
892
        (uint256 amount0, uint256 amount1) = currency0Invalid ? (1, 0) : (0, 1);
893
        vm.expectRevert(abi.encodeWithSelector(CurrencyLibrary.ERC20TransferFailed.selector, abi.encode(bytes32(0))));
894
        takeRouter.take(key, amount0, amount1);
895

                            
                        
896
        // should not revert when non zero amount passed in for valid currency
897
        // assertions inside takeRouter because it takes then settles
898
        (amount0, amount1) = currency0Invalid ? (0, 1) : (1, 0);
899
        takeRouter.take(key, amount0, amount1);
900
    }
901

                            
                        
902
    function test_take_succeedsWithPoolWithLiquidity() public {
903
        takeRouter.take(key, 1, 1); // assertions inside takeRouter because it takes then settles
904
    }
905

                            
                        
906
    function test_take_failsIfLocked() public {
907
        vm.expectRevert(IPoolManager.ManagerLocked.selector);
908
        manager.take(key.currency0, address(this), 1);
909
    }
910

                            
                        
911
    function test_take_succeedsWithPoolWithLiquidityWithNativeToken() public {
912
        takeRouter.take{value: 1}(nativeKey, 1, 1); // assertions inside takeRouter because it takes then settles
913
    }
914

                            
                        
915
    function test_settle_failsIfLocked() public {
916
        vm.expectRevert(IPoolManager.ManagerLocked.selector);
917
        manager.settle();
918
    }
919

                            
                        
920
    function test_settle_revertsSendingNativeWithToken() public noIsolate {
921
        manager.sync(key.currency0);
922
        vm.expectRevert(IPoolManager.NonZeroNativeValue.selector);
923
        settleRouter.settle{value: 1}();
924
    }
925

                            
                        
926
    function test_mint_failsIfLocked() public {
927
        vm.expectRevert(IPoolManager.ManagerLocked.selector);
928
        manager.mint(address(this), key.currency0.toId(), 1);
929
    }
930

                            
                        
931
    function test_burn_failsIfLocked() public {
932
        vm.expectRevert(IPoolManager.ManagerLocked.selector);
933
        manager.burn(address(this), key.currency0.toId(), 1);
934
    }
935

                            
                        
936
    function test_collectProtocolFees_ERC20_accumulateFees_gas() public {
937
        uint256 expectedFees = 10;
938

                            
                        
939
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(key.toId());
940
        assertEq(slot0ProtocolFee, 0);
941

                            
                        
942
        vm.prank(address(feeController));
943
        manager.setProtocolFee(key, MAX_PROTOCOL_FEE_BOTH_TOKENS);
944

                            
                        
945
        (,, slot0ProtocolFee,) = manager.getSlot0(key.toId());
946
        assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS);
947

                            
                        
948
        swapRouter.swap(
949
            key,
950
            IPoolManager.SwapParams(true, -10000, SQRT_PRICE_1_2),
951
            PoolSwapTest.TestSettings(false, false),
952
            ZERO_BYTES
953
        );
954

                            
                        
955
        assertEq(manager.protocolFeesAccrued(currency0), expectedFees);
956
        assertEq(manager.protocolFeesAccrued(currency1), 0);
957
        assertEq(currency0.balanceOf(address(1)), 0);
958
        vm.prank(address(feeController));
959
        manager.collectProtocolFees(address(1), currency0, expectedFees);
960
        snapLastCall("erc20 collect protocol fees");
961
        assertEq(currency0.balanceOf(address(1)), expectedFees);
962
        assertEq(manager.protocolFeesAccrued(currency0), 0);
963
    }
964

                            
                        
965
    function test_collectProtocolFees_ERC20_accumulateFees_exactOutput() public {
966
        uint256 expectedFees = 10;
967

                            
                        
968
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(key.toId());
969
        assertEq(slot0ProtocolFee, 0);
970

                            
                        
971
        vm.prank(address(feeController));
972
        manager.setProtocolFee(key, MAX_PROTOCOL_FEE_BOTH_TOKENS);
973

                            
                        
974
        (,, slot0ProtocolFee,) = manager.getSlot0(key.toId());
975
        assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS);
976

                            
                        
977
        swapRouter.swap(
978
            key,
979
            IPoolManager.SwapParams(true, 10000, SQRT_PRICE_1_2),
980
            PoolSwapTest.TestSettings(false, false),
981
            ZERO_BYTES
982
        );
983

                            
                        
984
        assertEq(manager.protocolFeesAccrued(currency0), expectedFees);
985
        assertEq(manager.protocolFeesAccrued(currency1), 0);
986
        assertEq(currency0.balanceOf(address(1)), 0);
987
        vm.prank(address(feeController));
988
        manager.collectProtocolFees(address(1), currency0, expectedFees);
989
        assertEq(currency0.balanceOf(address(1)), expectedFees);
990
        assertEq(manager.protocolFeesAccrued(currency0), 0);
991
    }
992

                            
                        
993
    function test_collectProtocolFees_ERC20_returnsAllFeesIf0IsProvidedAsParameter() public {
994
        uint256 expectedFees = 10;
995

                            
                        
996
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(key.toId());
997
        assertEq(slot0ProtocolFee, 0);
998

                            
                        
999
        vm.prank(address(feeController));
1000
        manager.setProtocolFee(key, MAX_PROTOCOL_FEE_BOTH_TOKENS);
1001

                            
                        
1002
        (,, slot0ProtocolFee,) = manager.getSlot0(key.toId());
1003
        assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS);
1004

                            
                        
1005
        swapRouter.swap(
1006
            key,
1007
            IPoolManager.SwapParams(false, -10000, TickMath.MAX_SQRT_PRICE - 1),
1008
            PoolSwapTest.TestSettings(false, false),
1009
            ZERO_BYTES
1010
        );
1011

                            
                        
1012
        assertEq(manager.protocolFeesAccrued(currency0), 0);
1013
        assertEq(manager.protocolFeesAccrued(currency1), expectedFees);
1014
        assertEq(currency1.balanceOf(address(1)), 0);
1015
        vm.prank(address(feeController));
1016
        manager.collectProtocolFees(address(1), currency1, 0);
1017
        assertEq(currency1.balanceOf(address(1)), expectedFees);
1018
        assertEq(manager.protocolFeesAccrued(currency1), 0);
1019
    }
1020

                            
                        
1021
    function test_collectProtocolFees_nativeToken_accumulateFees_gas() public {
1022
        uint256 expectedFees = 10;
1023
        Currency nativeCurrency = CurrencyLibrary.NATIVE;
1024

                            
                        
1025
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(nativeKey.toId());
1026
        assertEq(slot0ProtocolFee, 0);
1027

                            
                        
1028
        vm.prank(address(feeController));
1029
        manager.setProtocolFee(nativeKey, MAX_PROTOCOL_FEE_BOTH_TOKENS);
1030

                            
                        
1031
        (,, slot0ProtocolFee,) = manager.getSlot0(nativeKey.toId());
1032
        assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS);
1033

                            
                        
1034
        swapRouter.swap{value: 10000}(
1035
            nativeKey,
1036
            IPoolManager.SwapParams(true, -10000, SQRT_PRICE_1_2),
1037
            PoolSwapTest.TestSettings(false, false),
1038
            ZERO_BYTES
1039
        );
1040

                            
                        
1041
        assertEq(manager.protocolFeesAccrued(nativeCurrency), expectedFees);
1042
        assertEq(manager.protocolFeesAccrued(currency1), 0);
1043
        assertEq(nativeCurrency.balanceOf(address(1)), 0);
1044
        vm.prank(address(feeController));
1045
        manager.collectProtocolFees(address(1), nativeCurrency, expectedFees);
1046
        snapLastCall("native collect protocol fees");
1047
        assertEq(nativeCurrency.balanceOf(address(1)), expectedFees);
1048
        assertEq(manager.protocolFeesAccrued(nativeCurrency), 0);
1049
    }
1050

                            
                        
1051
    function test_collectProtocolFees_nativeToken_returnsAllFeesIf0IsProvidedAsParameter() public {
1052
        uint256 expectedFees = 10;
1053
        Currency nativeCurrency = CurrencyLibrary.NATIVE;
1054

                            
                        
1055
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(nativeKey.toId());
1056
        assertEq(slot0ProtocolFee, 0);
1057

                            
                        
1058
        vm.prank(address(feeController));
1059
        manager.setProtocolFee(nativeKey, MAX_PROTOCOL_FEE_BOTH_TOKENS);
1060

                            
                        
1061
        (,, slot0ProtocolFee,) = manager.getSlot0(nativeKey.toId());
1062
        assertEq(slot0ProtocolFee, MAX_PROTOCOL_FEE_BOTH_TOKENS);
1063

                            
                        
1064
        swapRouter.swap{value: 10000}(
1065
            nativeKey,
1066
            IPoolManager.SwapParams(true, -10000, SQRT_PRICE_1_2),
1067
            PoolSwapTest.TestSettings(false, false),
1068
            ZERO_BYTES
1069
        );
1070

                            
                        
1071
        assertEq(manager.protocolFeesAccrued(nativeCurrency), expectedFees);
1072
        assertEq(manager.protocolFeesAccrued(currency1), 0);
1073
        assertEq(nativeCurrency.balanceOf(address(1)), 0);
1074
        vm.prank(address(feeController));
1075
        manager.collectProtocolFees(address(1), nativeCurrency, 0);
1076
        assertEq(nativeCurrency.balanceOf(address(1)), expectedFees);
1077
        assertEq(manager.protocolFeesAccrued(nativeCurrency), 0);
1078
    }
1079

                            
                        
1080
    function test_unlock_EmitsCorrectId() public {
1081
        vm.expectEmit(false, false, false, true);
1082
        emit UnlockCallback();
1083
        emptyUnlockRouter.unlock();
1084
    }
1085

                            
                        
1086
    Action[] actions;
1087

                            
                        
1088
    function test_unlock_cannotBeCalledTwiceByCaller() public {
1089
        actions = [Action.NESTED_SELF_UNLOCK];
1090
        nestedActionRouter.unlock(abi.encode(actions));
1091
    }
1092

                            
                        
1093
    function test_unlock_cannotBeCalledTwiceByDifferentCallers() public {
1094
        actions = [Action.NESTED_EXECUTOR_UNLOCK];
1095
        nestedActionRouter.unlock(abi.encode(actions));
1096
    }
1097

                            
                        
1098
    // function testExtsloadForPoolPrice() public {
1099
    //     IPoolManager.key = IPoolManager.PoolKey({
1100
    //         currency0: currency0,
1101
    //         currency1: currency1,
1102
    //         fee: 100,
1103
    //         hooks: IHooks(address(0)),
1104
    //         tickSpacing: 10
1105
    //     });
1106
    //     manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
1107

                            
                        
1108
    //     PoolId poolId = key.toId();
1109
    //     bytes32 slot0Bytes = manager.extsload(keccak256(abi.encode(poolId, POOL_SLOT)));
1110
    //     snapLastCall("poolExtsloadSlot0");
1111

                            
                        
1112
    //     uint160 sqrtPriceX96Extsload;
1113
    //     assembly {
1114
    //         sqrtPriceX96Extsload := and(slot0Bytes, sub(shl(160, 1), 1))
1115
    //     }
1116
    //     (uint160 sqrtPriceX96Slot0,,,,,) = manager.getSlot0(poolId);
1117

                            
                        
1118
    //     // assert that extsload loads the correct storage slot which matches the true slot0
1119
    //     assertEq(sqrtPriceX96Extsload, sqrtPriceX96Slot0);
1120
    // }
1121

                            
                        
1122
    // function testExtsloadMultipleSlots() public {
1123
    //     IPoolManager.key = IPoolManager.PoolKey({
1124
    //         currency0: currency0,
1125
    //         currency1: currency1,
1126
    //         fee: 100,
1127
    //         hooks: IHooks(address(0)),
1128
    //         tickSpacing: 10
1129
    //     });
1130
    //     manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
1131

                            
                        
1132
    //     // populate feeGrowthGlobalX128 struct w/ modify + swap
1133
    //     modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-120, 120, 5 ether, 0));
1134
    //     swapRouter.swap(
1135
    //         key,
1136
    //         IPoolManager.SwapParams(false, 1 ether, TickMath.MAX_SQRT_PRICE - 1),
1137
    //         PoolSwapTest.TestSettings(true, true)
1138
    //     );
1139
    //     swapRouter.swap(
1140
    //         key,
1141
    //         IPoolManager.SwapParams(true, 5 ether, TickMath.MIN_SQRT_PRICE + 1),
1142
    //         PoolSwapTest.TestSettings(true, true)
1143
    //     );
1144

                            
                        
1145
    //     PoolId poolId = key.toId();
1146
    //     bytes memory value = manager.extsload(bytes32(uint256(keccak256(abi.encode(poolId, POOL_SLOT))) + 1), 2);
1147
    //     snapLastCall("poolExtsloadTickInfoStruct");
1148

                            
                        
1149
    //     uint256 feeGrowthGlobal0X128Extsload;
1150
    //     uint256 feeGrowthGlobal1X128Extsload;
1151
    //     assembly {
1152
    //         feeGrowthGlobal0X128Extsload := and(mload(add(value, 0x20)), sub(shl(256, 1), 1))
1153
    //         feeGrowthGlobal1X128Extsload := and(mload(add(value, 0x40)), sub(shl(256, 1), 1))
1154
    //     }
1155

                            
                        
1156
    //     assertEq(feeGrowthGlobal0X128Extsload, 408361710565269213475534193967158);
1157
    //     assertEq(feeGrowthGlobal1X128Extsload, 204793365386061595215803889394593);
1158
    // }
1159

                            
                        
1160
    function test_getPosition() public view {
1161
        Position.Info memory managerPosition =
1162
            manager.getPosition(key.toId(), address(modifyLiquidityRouter), -120, 120, 0);
1163
        assert(LIQUIDITY_PARAMS.liquidityDelta > 0);
1164
        assertEq(managerPosition.liquidity, uint128(uint256(LIQUIDITY_PARAMS.liquidityDelta)));
1165
    }
1166

                            
                        
1167
    function supportsInterface(bytes4) external pure returns (bool) {
1168
        return true;
1169
    }
1170
}
1171

                            
                        

Lines covered: 0 / 154 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {IHooks} from "../src/interfaces/IHooks.sol";
6
import {Hooks} from "../src/libraries/Hooks.sol";
7
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
8
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
9
import {PoolManager} from "../src/PoolManager.sol";
10
import {TickMath} from "../src/libraries/TickMath.sol";
11
import {Pool} from "../src/libraries/Pool.sol";
12
import {Deployers} from "./utils/Deployers.sol";
13
import {Constants} from "./utils/Constants.sol";
14
import {Currency, CurrencyLibrary} from "../src/types/Currency.sol";
15
import {MockHooks} from "../src/test/MockHooks.sol";
16
import {MockContract} from "../src/test/MockContract.sol";
17
import {EmptyTestHooks} from "../src/test/EmptyTestHooks.sol";
18
import {PoolKey} from "../src/types/PoolKey.sol";
19
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
20
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
21
import {LPFeeLibrary} from "../src/libraries/LPFeeLibrary.sol";
22
import {ProtocolFeeControllerTest} from "../src/test/ProtocolFeeControllerTest.sol";
23
import {IProtocolFeeController} from "../src/interfaces/IProtocolFeeController.sol";
24
import {ProtocolFeeLibrary} from "../src/libraries/ProtocolFeeLibrary.sol";
25
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
26

                            
                        
27
contract PoolManagerInitializeTest is Test, Deployers, GasSnapshot {
28
    using Hooks for IHooks;
29
    using PoolIdLibrary for PoolKey;
30
    using LPFeeLibrary for uint24;
31
    using ProtocolFeeLibrary for uint24;
32
    using StateLibrary for IPoolManager;
33

                            
                        
34
    event Initialize(
35
        PoolId indexed poolId,
36
        Currency indexed currency0,
37
        Currency indexed currency1,
38
        uint24 fee,
39
        int24 tickSpacing,
40
        IHooks hooks
41
    );
42

                            
                        
43
    function setUp() public {
44
        deployFreshManagerAndRouters();
45
        deployMintAndApprove2Currencies();
46

                            
                        
47
        uninitializedKey = PoolKey({
48
            currency0: currency0,
49
            currency1: currency1,
50
            fee: 3000,
51
            hooks: IHooks(Constants.ADDRESS_ZERO),
52
            tickSpacing: 60
53
        });
54
    }
55

                            
                        
56
    function test_fuzz_initialize(PoolKey memory key0, uint160 sqrtPriceX96) public {
57
        // Assumptions tested in Pool.t.sol
58
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
59

                            
                        
60
        // tested in Hooks.t.sol
61
        key0.hooks = IHooks(Constants.ADDRESS_ZERO);
62

                            
                        
63
        if (key0.tickSpacing > manager.MAX_TICK_SPACING()) {
64
            vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooLarge.selector, key0.tickSpacing));
65
            manager.initialize(key0, sqrtPriceX96, ZERO_BYTES);
66
        } else if (key0.tickSpacing < manager.MIN_TICK_SPACING()) {
67
            vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, key0.tickSpacing));
68
            manager.initialize(key0, sqrtPriceX96, ZERO_BYTES);
69
        } else if (key0.currency0 >= key0.currency1) {
70
            vm.expectRevert(
71
                abi.encodeWithSelector(
72
                    IPoolManager.CurrenciesOutOfOrderOrEqual.selector, key0.currency0, key0.currency1
73
                )
74
            );
75
            manager.initialize(key0, sqrtPriceX96, ZERO_BYTES);
76
        } else if (!key0.hooks.isValidHookAddress(key0.fee)) {
77
            vm.expectRevert(abi.encodeWithSelector(Hooks.HookAddressNotValid.selector, address(key0.hooks)));
78
            manager.initialize(key0, sqrtPriceX96, ZERO_BYTES);
79
        } else if ((key0.fee != LPFeeLibrary.DYNAMIC_FEE_FLAG) && (key0.fee > 1000000)) {
80
            vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, key0.fee));
81
            manager.initialize(key0, sqrtPriceX96, ZERO_BYTES);
82
        } else {
83
            vm.expectEmit(true, true, true, true);
84
            emit Initialize(key0.toId(), key0.currency0, key0.currency1, key0.fee, key0.tickSpacing, key0.hooks);
85
            manager.initialize(key0, sqrtPriceX96, ZERO_BYTES);
86

                            
                        
87
            (uint160 slot0SqrtPriceX96,, uint24 slot0ProtocolFee,) = manager.getSlot0(key0.toId());
88
            assertEq(slot0SqrtPriceX96, sqrtPriceX96);
89
            assertEq(slot0ProtocolFee, 0);
90
        }
91
    }
92

                            
                        
93
    function test_initialize_forNativeTokens(uint160 sqrtPriceX96) public {
94
        // Assumptions tested in Pool.t.sol
95
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
96
        uninitializedKey.currency0 = CurrencyLibrary.NATIVE;
97

                            
                        
98
        vm.expectEmit(true, true, true, true);
99
        emit Initialize(
100
            uninitializedKey.toId(),
101
            uninitializedKey.currency0,
102
            uninitializedKey.currency1,
103
            uninitializedKey.fee,
104
            uninitializedKey.tickSpacing,
105
            uninitializedKey.hooks
106
        );
107
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
108

                            
                        
109
        (uint160 slot0SqrtPriceX96, int24 slot0Tick, uint24 slot0ProtocolFee,) =
110
            manager.getSlot0(uninitializedKey.toId());
111
        assertEq(slot0SqrtPriceX96, sqrtPriceX96);
112
        assertEq(slot0ProtocolFee, 0);
113
        assertEq(slot0Tick, TickMath.getTickAtSqrtPrice(sqrtPriceX96));
114
    }
115

                            
                        
116
    function test_initialize_succeedsWithHooks(uint160 sqrtPriceX96) public {
117
        // Assumptions tested in Pool.t.sol
118
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
119

                            
                        
120
        address payable mockAddr = payable(address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG)));
121
        address payable hookAddr = payable(Constants.ALL_HOOKS);
122

                            
                        
123
        vm.etch(hookAddr, vm.getDeployedCode("EmptyTestHooks.sol:EmptyTestHooks"));
124
        MockContract mockContract = new MockContract();
125
        vm.etch(mockAddr, address(mockContract).code);
126

                            
                        
127
        MockContract(mockAddr).setImplementation(hookAddr);
128

                            
                        
129
        uninitializedKey.hooks = IHooks(mockAddr);
130

                            
                        
131
        int24 tick = manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
132
        (uint160 slot0SqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId());
133
        assertEq(slot0SqrtPriceX96, sqrtPriceX96, "sqrtPrice");
134

                            
                        
135
        bytes32 beforeSelector = MockHooks.beforeInitialize.selector;
136
        bytes memory beforeParams = abi.encode(address(this), uninitializedKey, sqrtPriceX96, ZERO_BYTES);
137

                            
                        
138
        bytes32 afterSelector = MockHooks.afterInitialize.selector;
139
        bytes memory afterParams = abi.encode(address(this), uninitializedKey, sqrtPriceX96, tick, ZERO_BYTES);
140

                            
                        
141
        assertEq(MockContract(mockAddr).timesCalledSelector(beforeSelector), 1, "beforeSelector count");
142
        assertTrue(MockContract(mockAddr).calledWithSelector(beforeSelector, beforeParams), "beforeSelector params");
143
        assertEq(MockContract(mockAddr).timesCalledSelector(afterSelector), 1, "afterSelector count");
144
        assertTrue(MockContract(mockAddr).calledWithSelector(afterSelector, afterParams), "afterSelector params");
145
    }
146

                            
                        
147
    function test_initialize_succeedsWithMaxTickSpacing(uint160 sqrtPriceX96) public {
148
        // Assumptions tested in Pool.t.sol
149
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
150

                            
                        
151
        uninitializedKey.tickSpacing = manager.MAX_TICK_SPACING();
152

                            
                        
153
        vm.expectEmit(true, true, true, true);
154
        emit Initialize(
155
            uninitializedKey.toId(),
156
            uninitializedKey.currency0,
157
            uninitializedKey.currency1,
158
            uninitializedKey.fee,
159
            uninitializedKey.tickSpacing,
160
            uninitializedKey.hooks
161
        );
162

                            
                        
163
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
164
    }
165

                            
                        
166
    function test_initialize_succeedsWithEmptyHooks(uint160 sqrtPriceX96) public {
167
        // Assumptions tested in Pool.t.sol
168
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
169

                            
                        
170
        address allHooksAddr = Constants.ALL_HOOKS;
171

                            
                        
172
        MockHooks impl = new MockHooks();
173
        vm.etch(allHooksAddr, address(impl).code);
174
        MockHooks mockHooks = MockHooks(allHooksAddr);
175

                            
                        
176
        uninitializedKey.hooks = mockHooks;
177

                            
                        
178
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
179
        (uint160 slot0SqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId());
180
        assertEq(slot0SqrtPriceX96, sqrtPriceX96);
181
    }
182

                            
                        
183
    function test_initialize_revertsWithIdenticalTokens(uint160 sqrtPriceX96) public {
184
        // Assumptions tested in Pool.t.sol
185
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
186

                            
                        
187
        // Both currencies are currency0
188
        uninitializedKey.currency1 = currency0;
189

                            
                        
190
        vm.expectRevert(
191
            abi.encodeWithSelector(
192
                IPoolManager.CurrenciesOutOfOrderOrEqual.selector,
193
                Currency.unwrap(currency0),
194
                Currency.unwrap(currency0)
195
            )
196
        );
197
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
198
    }
199

                            
                        
200
    function test_initialize_revertsWithSameTokenCombo(uint160 sqrtPriceX96) public {
201
        // Assumptions tested in Pool.t.sol
202
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
203

                            
                        
204
        uninitializedKey.currency1 = currency0;
205
        uninitializedKey.currency0 = currency1;
206

                            
                        
207
        vm.expectRevert(
208
            abi.encodeWithSelector(
209
                IPoolManager.CurrenciesOutOfOrderOrEqual.selector,
210
                Currency.unwrap(currency1),
211
                Currency.unwrap(currency0)
212
            )
213
        );
214
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
215
    }
216

                            
                        
217
    function test_initialize_fetchFeeWhenController(uint24 protocolFee) public {
218
        manager.setProtocolFeeController(feeController);
219
        feeController.setProtocolFeeForPool(uninitializedKey.toId(), protocolFee);
220

                            
                        
221
        uint16 fee0 = protocolFee.getZeroForOneFee();
222
        uint16 fee1 = protocolFee.getOneForZeroFee();
223

                            
                        
224
        manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES);
225

                            
                        
226
        (uint160 slot0SqrtPriceX96,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId());
227
        assertEq(slot0SqrtPriceX96, SQRT_PRICE_1_1);
228
        if ((fee0 > 1000) || (fee1 > 1000)) {
229
            assertEq(slot0ProtocolFee, 0);
230
        } else {
231
            assertEq(slot0ProtocolFee, protocolFee);
232
        }
233
    }
234

                            
                        
235
    function test_initialize_revertsWhenPoolAlreadyInitialized(uint160 sqrtPriceX96) public {
236
        // Assumptions tested in Pool.t.sol
237
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
238

                            
                        
239
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
240
        vm.expectRevert(Pool.PoolAlreadyInitialized.selector);
241
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
242
    }
243

                            
                        
244
    function test_initialize_failsWithIncorrectSelectors() public {
245
        address hookAddr = address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG));
246

                            
                        
247
        MockHooks impl = new MockHooks();
248
        vm.etch(hookAddr, address(impl).code);
249
        MockHooks mockHooks = MockHooks(hookAddr);
250

                            
                        
251
        uninitializedKey.hooks = mockHooks;
252

                            
                        
253
        mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, bytes4(0xdeadbeef));
254
        mockHooks.setReturnValue(mockHooks.afterInitialize.selector, bytes4(0xdeadbeef));
255

                            
                        
256
        // Fails at beforeInitialize hook.
257
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
258
        manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES);
259

                            
                        
260
        // Fail at afterInitialize hook.
261
        mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, mockHooks.beforeInitialize.selector);
262
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
263
        manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES);
264
    }
265

                            
                        
266
    function test_initialize_succeedsWithCorrectSelectors() public {
267
        address hookAddr = address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG));
268

                            
                        
269
        MockHooks impl = new MockHooks();
270
        vm.etch(hookAddr, address(impl).code);
271
        MockHooks mockHooks = MockHooks(hookAddr);
272

                            
                        
273
        uninitializedKey.hooks = mockHooks;
274

                            
                        
275
        mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, mockHooks.beforeInitialize.selector);
276
        mockHooks.setReturnValue(mockHooks.afterInitialize.selector, mockHooks.afterInitialize.selector);
277

                            
                        
278
        vm.expectEmit(true, true, true, true);
279
        emit Initialize(
280
            uninitializedKey.toId(),
281
            uninitializedKey.currency0,
282
            uninitializedKey.currency1,
283
            uninitializedKey.fee,
284
            uninitializedKey.tickSpacing,
285
            uninitializedKey.hooks
286
        );
287

                            
                        
288
        manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES);
289
    }
290

                            
                        
291
    function test_initialize_failsIfTickSpaceTooLarge(uint160 sqrtPriceX96) public {
292
        // Assumptions tested in Pool.t.sol
293
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
294

                            
                        
295
        uninitializedKey.tickSpacing = manager.MAX_TICK_SPACING() + 1;
296

                            
                        
297
        vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooLarge.selector, uninitializedKey.tickSpacing));
298
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
299
    }
300

                            
                        
301
    function test_initialize_failsIfTickSpaceZero(uint160 sqrtPriceX96) public {
302
        // Assumptions tested in Pool.t.sol
303
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
304

                            
                        
305
        uninitializedKey.tickSpacing = 0;
306

                            
                        
307
        vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, uninitializedKey.tickSpacing));
308
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
309
    }
310

                            
                        
311
    function test_initialize_failsIfTickSpaceNeg(uint160 sqrtPriceX96) public {
312
        // Assumptions tested in Pool.t.sol
313
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
314

                            
                        
315
        uninitializedKey.tickSpacing = -1;
316

                            
                        
317
        vm.expectRevert(abi.encodeWithSelector(IPoolManager.TickSpacingTooSmall.selector, uninitializedKey.tickSpacing));
318
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
319
    }
320

                            
                        
321
    function test_initialize_succeedsWithOutOfBoundsFeeController(uint160 sqrtPriceX96) public {
322
        // Assumptions tested in Pool.t.sol
323
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
324

                            
                        
325
        manager.setProtocolFeeController(outOfBoundsFeeController);
326
        // expect initialize to succeed even though the controller reverts
327
        vm.expectEmit(true, true, true, true);
328
        emit Initialize(
329
            uninitializedKey.toId(),
330
            uninitializedKey.currency0,
331
            uninitializedKey.currency1,
332
            uninitializedKey.fee,
333
            uninitializedKey.tickSpacing,
334
            uninitializedKey.hooks
335
        );
336
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
337
        // protocol fees should default to 0
338
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId());
339
        assertEq(slot0ProtocolFee, 0);
340
    }
341

                            
                        
342
    function test_initialize_succeedsWithRevertingFeeController(uint160 sqrtPriceX96) public {
343
        // Assumptions tested in Pool.t.sol
344
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
345

                            
                        
346
        manager.setProtocolFeeController(revertingFeeController);
347
        // expect initialize to succeed even though the controller reverts
348
        vm.expectEmit(true, true, true, true);
349
        emit Initialize(
350
            uninitializedKey.toId(),
351
            uninitializedKey.currency0,
352
            uninitializedKey.currency1,
353
            uninitializedKey.fee,
354
            uninitializedKey.tickSpacing,
355
            uninitializedKey.hooks
356
        );
357
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
358
        // protocol fees should default to 0
359
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId());
360
        assertEq(slot0ProtocolFee, 0);
361
    }
362

                            
                        
363
    function test_initialize_succeedsWithOverflowFeeController(uint160 sqrtPriceX96) public {
364
        // Assumptions tested in Pool.t.sol
365
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
366

                            
                        
367
        manager.setProtocolFeeController(overflowFeeController);
368
        // expect initialize to succeed
369
        vm.expectEmit(true, true, true, true);
370
        emit Initialize(
371
            uninitializedKey.toId(),
372
            uninitializedKey.currency0,
373
            uninitializedKey.currency1,
374
            uninitializedKey.fee,
375
            uninitializedKey.tickSpacing,
376
            uninitializedKey.hooks
377
        );
378
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
379
        // protocol fees should default to 0
380
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId());
381
        assertEq(slot0ProtocolFee, 0);
382
    }
383

                            
                        
384
    function test_initialize_succeedsWithWrongReturnSizeFeeController(uint160 sqrtPriceX96) public {
385
        // Assumptions tested in Pool.t.sol
386
        sqrtPriceX96 = uint160(bound(sqrtPriceX96, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE - 1));
387

                            
                        
388
        manager.setProtocolFeeController(invalidReturnSizeFeeController);
389
        // expect initialize to succeed
390
        vm.expectEmit(true, true, true, true);
391
        emit Initialize(
392
            uninitializedKey.toId(),
393
            uninitializedKey.currency0,
394
            uninitializedKey.currency1,
395
            uninitializedKey.fee,
396
            uninitializedKey.tickSpacing,
397
            uninitializedKey.hooks
398
        );
399
        manager.initialize(uninitializedKey, sqrtPriceX96, ZERO_BYTES);
400
        // protocol fees should default to 0
401
        (,, uint24 slot0ProtocolFee,) = manager.getSlot0(uninitializedKey.toId());
402
        assertEq(slot0ProtocolFee, 0);
403
    }
404

                            
                        
405
    function test_initialize_gas() public {
406
        manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES);
407
        snapLastCall("initialize");
408
    }
409
}
410

                            
                        

Lines covered: 0 / 103 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.15;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
6
import {Currency} from "../src/types/Currency.sol";
7
import {ProtocolFeesImplementation} from "../src/test/ProtocolFeesImplementation.sol";
8
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
9
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
10
import {ProtocolFeeLibrary} from "../src/libraries/ProtocolFeeLibrary.sol";
11
import {PoolKey} from "../src/types/PoolKey.sol";
12
import {Currency} from "../src/types/Currency.sol";
13
import {Deployers} from "../test/utils/Deployers.sol";
14
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
15
import {IHooks} from "../src/interfaces/IHooks.sol";
16
import {Constants} from "../test/utils/Constants.sol";
17
import {
18
    ProtocolFeeControllerTest,
19
    OutOfBoundsProtocolFeeControllerTest,
20
    RevertingProtocolFeeControllerTest,
21
    OverflowProtocolFeeControllerTest,
22
    InvalidReturnSizeProtocolFeeControllerTest
23
} from "../src/test/ProtocolFeeControllerTest.sol";
24

                            
                        
25
contract ProtocolFeesTest is Test, GasSnapshot, Deployers {
26
    using PoolIdLibrary for PoolKey;
27
    using ProtocolFeeLibrary for uint24;
28

                            
                        
29
    event ProtocolFeeControllerUpdated(address indexed feeController);
30
    event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee);
31

                            
                        
32
    uint24 constant MAX_PROTOCOL_FEE_BOTH_TOKENS = (1000 << 12) | 1000; // 1000 1000
33

                            
                        
34
    ProtocolFeesImplementation protocolFees;
35

                            
                        
36
    function setUp() public {
37
        protocolFees = new ProtocolFeesImplementation(5000);
38
        feeController = new ProtocolFeeControllerTest();
39
        (currency0, currency1) = deployAndMint2Currencies();
40
        MockERC20(Currency.unwrap(currency0)).transfer(address(protocolFees), 2 ** 255);
41
    }
42

                            
                        
43
    function test_setProtocolFeeController_succeedsNoRevert() public {
44
        assertEq(address(protocolFees.protocolFeeController()), address(0));
45
        vm.expectEmit(true, false, false, false, address(protocolFees));
46
        emit ProtocolFeeControllerUpdated(address(feeController));
47
        protocolFees.setProtocolFeeController(feeController);
48
        assertEq(address(protocolFees.protocolFeeController()), address(feeController));
49
    }
50

                            
                        
51
    function test_setProtocolFeeController_revertsWithNotAuthorized() public {
52
        assertEq(address(protocolFees.protocolFeeController()), address(0));
53

                            
                        
54
        vm.prank(address(1)); // not the owner address
55
        vm.expectRevert("UNAUTHORIZED");
56
        protocolFees.setProtocolFeeController(feeController);
57
        assertEq(address(protocolFees.protocolFeeController()), address(0));
58
    }
59

                            
                        
60
    function test_setProtocolFee_succeeds_gas() public {
61
        PoolKey memory key = PoolKey(currency0, currency1, 3000, 60, IHooks(address(0)));
62
        protocolFees.setProtocolFeeController(feeController);
63
        // Set price to pretend that the pool is initialized
64
        protocolFees.setPrice(key, Constants.SQRT_PRICE_1_1);
65
        vm.prank(address(feeController));
66
        vm.expectEmit(true, false, false, true, address(protocolFees));
67
        emit ProtocolFeeUpdated(key.toId(), MAX_PROTOCOL_FEE_BOTH_TOKENS);
68
        protocolFees.setProtocolFee(key, MAX_PROTOCOL_FEE_BOTH_TOKENS);
69
        snapLastCall("set protocol fee");
70
    }
71

                            
                        
72
    function test_setProtocolFee_revertsWithInvalidCaller() public {
73
        protocolFees.setProtocolFeeController(feeController);
74
        vm.expectRevert(IProtocolFees.InvalidCaller.selector);
75
        protocolFees.setProtocolFee(key, 1);
76
    }
77

                            
                        
78
    function test_setProtocolFee_revertsWithInvalidFee() public {
79
        uint24 protocolFee = MAX_PROTOCOL_FEE_BOTH_TOKENS + 1;
80

                            
                        
81
        protocolFees.setProtocolFeeController(feeController);
82
        vm.prank(address(feeController));
83
        vm.expectRevert(abi.encodeWithSelector(IProtocolFees.ProtocolFeeTooLarge.selector, protocolFee));
84
        protocolFees.setProtocolFee(key, protocolFee);
85

                            
                        
86
        protocolFee = MAX_PROTOCOL_FEE_BOTH_TOKENS + (1 << 12);
87
        vm.prank(address(feeController));
88
        vm.expectRevert(abi.encodeWithSelector(IProtocolFees.ProtocolFeeTooLarge.selector, protocolFee));
89
        protocolFees.setProtocolFee(key, protocolFee);
90
    }
91

                            
                        
92
    function test_fuzz_setProtocolFee(PoolKey memory key, uint24 protocolFee) public {
93
        protocolFees.setProtocolFeeController(feeController);
94
        // Set price to pretend that the pool is initialized
95
        protocolFees.setPrice(key, Constants.SQRT_PRICE_1_1);
96
        uint16 fee0 = protocolFee.getZeroForOneFee();
97
        uint16 fee1 = protocolFee.getOneForZeroFee();
98
        vm.prank(address(feeController));
99
        if ((fee0 > 1000) || (fee1 > 1000)) {
100
            vm.expectRevert(abi.encodeWithSelector(IProtocolFees.ProtocolFeeTooLarge.selector, protocolFee));
101
            protocolFees.setProtocolFee(key, protocolFee);
102
        } else {
103
            vm.expectEmit(true, false, false, true, address(protocolFees));
104
            emit IProtocolFees.ProtocolFeeUpdated(key.toId(), protocolFee);
105
            protocolFees.setProtocolFee(key, protocolFee);
106
        }
107
    }
108

                            
                        
109
    function test_collectProtocolFees_revertsWithInvalidCaller() public {
110
        vm.expectRevert(IProtocolFees.InvalidCaller.selector);
111
        protocolFees.collectProtocolFees(address(1), currency0, 0);
112
    }
113

                            
                        
114
    function test_collectProtocolFees_succeeds() public {
115
        // set a balance of protocol fees that can be collected
116
        protocolFees.updateProtocolFees(currency0, 100);
117
        assertEq(protocolFees.protocolFeesAccrued(currency0), 100);
118

                            
                        
119
        protocolFees.setProtocolFeeController(feeController);
120
        vm.prank(address(feeController));
121
        protocolFees.collectProtocolFees(address(this), currency0, 100);
122
        assertEq(protocolFees.protocolFeesAccrued(currency0), 0);
123
        assertEq(currency0.balanceOf(address(this)), 100);
124
    }
125

                            
                        
126
    function test_fuzz_collectProtocolFees(address recipient, uint256 amount, uint256 feesAccrued) public {
127
        vm.assume(feesAccrued <= currency0.balanceOf(address(protocolFees)));
128

                            
                        
129
        uint256 recipientBalanceBefore = currency0.balanceOf(recipient);
130
        uint256 senderBalanceBefore = currency0.balanceOf(address(protocolFees));
131

                            
                        
132
        // set a balance of protocol fees that can be collected
133
        protocolFees.updateProtocolFees(currency0, feesAccrued);
134
        assertEq(protocolFees.protocolFeesAccrued(currency0), feesAccrued);
135
        if (amount == 0) {
136
            amount = protocolFees.protocolFeesAccrued(currency0);
137
        }
138

                            
                        
139
        protocolFees.setProtocolFeeController(feeController);
140
        vm.prank(address(feeController));
141
        if (amount > feesAccrued) {
142
            vm.expectRevert();
143
        }
144
        uint256 amountCollected = protocolFees.collectProtocolFees(recipient, currency0, amount);
145

                            
                        
146
        if (amount <= feesAccrued) {
147
            if (recipient == address(protocolFees)) {
148
                assertEq(currency0.balanceOf(recipient), recipientBalanceBefore);
149
            } else {
150
                assertEq(currency0.balanceOf(recipient), recipientBalanceBefore + amount);
151
                assertEq(currency0.balanceOf(address(protocolFees)), senderBalanceBefore - amount);
152
            }
153
            assertEq(protocolFees.protocolFeesAccrued(currency0), feesAccrued - amount);
154
            assertEq(amountCollected, amount);
155
        }
156
    }
157

                            
                        
158
    function test_updateProtocolFees_succeeds() public {
159
        // set a starting balance of protocol fees
160
        protocolFees.updateProtocolFees(currency0, 100);
161
        assertEq(protocolFees.protocolFeesAccrued(currency0), 100);
162

                            
                        
163
        protocolFees.updateProtocolFees(currency0, 200);
164
        assertEq(protocolFees.protocolFeesAccrued(currency0), 300);
165
    }
166

                            
                        
167
    function test_fuzz_updateProtocolFees(uint256 amount, uint256 startingAmount) public {
168
        // set a starting balance of protocol fees
169
        protocolFees.updateProtocolFees(currency0, startingAmount);
170
        assertEq(protocolFees.protocolFeesAccrued(currency0), startingAmount);
171

                            
                        
172
        uint256 newAmount;
173
        unchecked {
174
            newAmount = startingAmount + amount;
175
        }
176

                            
                        
177
        protocolFees.updateProtocolFees(currency0, amount);
178
        assertEq(protocolFees.protocolFeesAccrued(currency0), newAmount);
179
    }
180

                            
                        
181
    function test_fetchProtocolFee_succeeds() public {
182
        protocolFees.setProtocolFeeController(feeController);
183
        vm.prank(address(feeController));
184
        (bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key);
185
        assertTrue(success);
186
        assertEq(protocolFee, 0);
187
    }
188

                            
                        
189
    function test_fetchProtocolFee_outOfBounds() public {
190
        outOfBoundsFeeController = new OutOfBoundsProtocolFeeControllerTest();
191
        protocolFees.setProtocolFeeController(outOfBoundsFeeController);
192
        vm.prank(address(outOfBoundsFeeController));
193
        (bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key);
194
        assertFalse(success);
195
        assertEq(protocolFee, 0);
196
    }
197

                            
                        
198
    function test_fetchProtocolFee_overflowFee() public {
199
        overflowFeeController = new OverflowProtocolFeeControllerTest();
200
        protocolFees.setProtocolFeeController(overflowFeeController);
201
        vm.prank(address(overflowFeeController));
202
        (bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key);
203
        assertFalse(success);
204
        assertEq(protocolFee, 0);
205
    }
206

                            
                        
207
    function test_fetchProtocolFee_invalidReturnSize() public {
208
        invalidReturnSizeFeeController = new InvalidReturnSizeProtocolFeeControllerTest();
209
        protocolFees.setProtocolFeeController(invalidReturnSizeFeeController);
210
        vm.prank(address(invalidReturnSizeFeeController));
211
        (bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key);
212
        assertFalse(success);
213
        assertEq(protocolFee, 0);
214
    }
215

                            
                        
216
    function test_fetchProtocolFee_revert() public {
217
        revertingFeeController = new RevertingProtocolFeeControllerTest();
218
        protocolFees.setProtocolFeeController(revertingFeeController);
219
        vm.prank(address(revertingFeeController));
220
        (bool success, uint24 protocolFee) = protocolFees.fetchProtocolFee(key);
221
        assertFalse(success);
222
        assertEq(protocolFee, 0);
223
    }
224
}
225

                            
                        

Lines covered: 0 / 59 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Vm} from "forge-std/Vm.sol";
6
import {PoolId, PoolIdLibrary} from "../src/types/PoolId.sol";
7
import {Hooks} from "../src/libraries/Hooks.sol";
8
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
9
import {IProtocolFees} from "../src/interfaces/IProtocolFees.sol";
10
import {IHooks} from "../src/interfaces/IHooks.sol";
11
import {PoolKey} from "../src/types/PoolKey.sol";
12
import {PoolManager} from "../src/PoolManager.sol";
13
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
14
import {Deployers} from "./utils/Deployers.sol";
15
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
16
import {Currency} from "../src/types/Currency.sol";
17
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
18
import {Constants} from "../test/utils/Constants.sol";
19
import {SkipCallsTestHook} from "../src/test/SkipCallsTestHook.sol";
20

                            
                        
21
contract SkipCallsTest is Test, Deployers, GasSnapshot {
22
    using PoolIdLibrary for PoolKey;
23

                            
                        
24
    PoolSwapTest.TestSettings testSettings = PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
25

                            
                        
26
    function deploy(SkipCallsTestHook skipCallsTestHook) private {
27
        SkipCallsTestHook impl = new SkipCallsTestHook();
28
        vm.etch(address(skipCallsTestHook), address(impl).code);
29
        deployFreshManagerAndRouters();
30
        skipCallsTestHook.setManager(IPoolManager(manager));
31
        deployMintAndApprove2Currencies();
32

                            
                        
33
        assertEq(skipCallsTestHook.counter(), 0);
34

                            
                        
35
        (key,) = initPool(currency0, currency1, IHooks(address(skipCallsTestHook)), 3000, SQRT_PRICE_1_1, ZERO_BYTES);
36
    }
37

                            
                        
38
    function approveAndAddLiquidity(SkipCallsTestHook skipCallsTestHook) private {
39
        MockERC20(Currency.unwrap(key.currency0)).approve(address(skipCallsTestHook), Constants.MAX_UINT256);
40
        MockERC20(Currency.unwrap(key.currency1)).approve(address(skipCallsTestHook), Constants.MAX_UINT256);
41
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this)));
42
    }
43

                            
                        
44
    function test_beforeInitialize_skipIfCalledByHook() public {
45
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
46
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_INITIALIZE_FLAG))
47
        );
48

                            
                        
49
        // initializes pool and increments counter
50
        deploy(skipCallsTestHook);
51
        assertEq(skipCallsTestHook.counter(), 1);
52
    }
53

                            
                        
54
    function test_afterInitialize_skipIfCalledByHook() public {
55
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
56
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_INITIALIZE_FLAG))
57
        );
58

                            
                        
59
        // initializes pool and increments counter
60
        deploy(skipCallsTestHook);
61
        assertEq(skipCallsTestHook.counter(), 1);
62
    }
63

                            
                        
64
    function test_beforeAddLiquidity_skipIfCalledByHook() public {
65
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
66
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_ADD_LIQUIDITY_FLAG))
67
        );
68

                            
                        
69
        deploy(skipCallsTestHook);
70
        assertEq(skipCallsTestHook.counter(), 0);
71

                            
                        
72
        // adds liquidity and increments counter
73
        approveAndAddLiquidity(skipCallsTestHook);
74
        assertEq(skipCallsTestHook.counter(), 1);
75
        // adds liquidity again and increments counter
76
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this)));
77
        assertEq(skipCallsTestHook.counter(), 2);
78
    }
79

                            
                        
80
    function test_afterAddLiquidity_skipIfCalledByHook() public {
81
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
82
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_ADD_LIQUIDITY_FLAG))
83
        );
84

                            
                        
85
        deploy(skipCallsTestHook);
86
        assertEq(skipCallsTestHook.counter(), 0);
87

                            
                        
88
        // adds liquidity and increments counter
89
        approveAndAddLiquidity(skipCallsTestHook);
90
        assertEq(skipCallsTestHook.counter(), 1);
91
        // adds liquidity and increments counter again
92
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this)));
93
        assertEq(skipCallsTestHook.counter(), 2);
94
    }
95

                            
                        
96
    function test_beforeRemoveLiquidity_skipIfCalledByHook() public {
97
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
98
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG))
99
        );
100

                            
                        
101
        deploy(skipCallsTestHook);
102
        approveAndAddLiquidity(skipCallsTestHook);
103
        assertEq(skipCallsTestHook.counter(), 0);
104

                            
                        
105
        // removes liquidity and increments counter
106
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, abi.encode(address(this)));
107
        assertEq(skipCallsTestHook.counter(), 1);
108
        // adds liquidity again
109
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this)));
110
        // removes liquidity again and increments counter
111
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, abi.encode(address(this)));
112
        assertEq(skipCallsTestHook.counter(), 2);
113
    }
114

                            
                        
115
    function test_afterRemoveLiquidity_skipIfCalledByHook() public {
116
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
117
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG))
118
        );
119

                            
                        
120
        deploy(skipCallsTestHook);
121
        approveAndAddLiquidity(skipCallsTestHook);
122
        assertEq(skipCallsTestHook.counter(), 0);
123

                            
                        
124
        // removes liquidity and increments counter
125
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, abi.encode(address(this)));
126
        assertEq(skipCallsTestHook.counter(), 1);
127
        // adds liquidity again
128
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, abi.encode(address(this)));
129
        // removes liquidity again and increments counter
130
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, abi.encode(address(this)));
131
        assertEq(skipCallsTestHook.counter(), 2);
132
    }
133

                            
                        
134
    function test_beforeSwap_skipIfCalledByHook() public {
135
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
136
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_SWAP_FLAG))
137
        );
138

                            
                        
139
        deploy(skipCallsTestHook);
140
        approveAndAddLiquidity(skipCallsTestHook);
141
        assertEq(skipCallsTestHook.counter(), 0);
142

                            
                        
143
        // swaps and increments counter
144
        swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this)));
145
        assertEq(skipCallsTestHook.counter(), 1);
146
        // swaps again and increments counter
147
        swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this)));
148
        assertEq(skipCallsTestHook.counter(), 2);
149
    }
150

                            
                        
151
    function test_gas_beforeSwap_skipIfCalledByHook() public {
152
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
153
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_SWAP_FLAG))
154
        );
155

                            
                        
156
        deploy(skipCallsTestHook);
157
        approveAndAddLiquidity(skipCallsTestHook);
158
        assertEq(skipCallsTestHook.counter(), 0);
159

                            
                        
160
        // swaps and increments counter
161
        swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this)));
162
        snapLastCall("swap skips hook call if hook is caller");
163
        assertEq(skipCallsTestHook.counter(), 1);
164
    }
165

                            
                        
166
    function test_afterSwap_skipIfCalledByHook() public {
167
        SkipCallsTestHook skipCallsTestHook =
168
            SkipCallsTestHook(address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_SWAP_FLAG)));
169

                            
                        
170
        deploy(skipCallsTestHook);
171
        approveAndAddLiquidity(skipCallsTestHook);
172
        assertEq(skipCallsTestHook.counter(), 0);
173

                            
                        
174
        // swaps and increments counter
175
        swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this)));
176
        assertEq(skipCallsTestHook.counter(), 1);
177
        // swaps again and increments counter
178
        swapRouter.swap(key, SWAP_PARAMS, testSettings, abi.encode(address(this)));
179
        assertEq(skipCallsTestHook.counter(), 2);
180
    }
181

                            
                        
182
    function test_beforeDonate_skipIfCalledByHook() public {
183
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
184
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.BEFORE_DONATE_FLAG))
185
        );
186

                            
                        
187
        deploy(skipCallsTestHook);
188
        approveAndAddLiquidity(skipCallsTestHook);
189
        assertEq(skipCallsTestHook.counter(), 0);
190

                            
                        
191
        // donates and increments counter
192
        donateRouter.donate(key, 100, 200, abi.encode(address(this)));
193
        assertEq(skipCallsTestHook.counter(), 1);
194
        // donates again and increments counter
195
        donateRouter.donate(key, 100, 200, abi.encode(address(this)));
196
        assertEq(skipCallsTestHook.counter(), 2);
197
    }
198

                            
                        
199
    function test_afterDonate_skipIfCalledByHook() public {
200
        SkipCallsTestHook skipCallsTestHook = SkipCallsTestHook(
201
            address(uint160(type(uint160).max & clearAllHookPermissionsMask | Hooks.AFTER_DONATE_FLAG))
202
        );
203

                            
                        
204
        deploy(skipCallsTestHook);
205
        approveAndAddLiquidity(skipCallsTestHook);
206
        assertEq(skipCallsTestHook.counter(), 0);
207

                            
                        
208
        // donates and increments counter
209
        donateRouter.donate(key, 100, 200, abi.encode(address(this)));
210
        assertEq(skipCallsTestHook.counter(), 1);
211
        // donates again and increments counter
212
        donateRouter.donate(key, 100, 200, abi.encode(address(this)));
213
        assertEq(skipCallsTestHook.counter(), 2);
214
    }
215
}
216

                            
                        

Lines covered: 0 / 111 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
6
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
7

                            
                        
8
import {Deployers} from "./utils/Deployers.sol";
9
import {IHooks} from "../src/interfaces/IHooks.sol";
10
import {Currency} from "../src/types/Currency.sol";
11
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
12
import {PoolSwapTest} from "../src/test/PoolSwapTest.sol";
13
import {IUnlockCallback} from "../src/interfaces/callback/IUnlockCallback.sol";
14
import {PoolKey} from "../src/types/PoolKey.sol";
15
import {ActionsRouter, Actions} from "../src/test/ActionsRouter.sol";
16
import {SafeCast} from "../src/libraries/SafeCast.sol";
17
import {CurrencyReserves} from "../src/libraries/CurrencyReserves.sol";
18
import {StateLibrary} from "../src/libraries/StateLibrary.sol";
19
import {TransientStateLibrary} from "../src/libraries/TransientStateLibrary.sol";
20
import {NativeERC20} from "../src/test/NativeERC20.sol";
21
import {IPoolManager} from "../src/interfaces/IPoolManager.sol";
22

                            
                        
23
contract SyncTest is Test, Deployers, GasSnapshot {
24
    using StateLibrary for IPoolManager;
25
    using TransientStateLibrary for IPoolManager;
26

                            
                        
27
    // PoolManager has no balance of currency2.
28
    Currency currency2;
29
    ActionsRouter router;
30

                            
                        
31
    function setUp() public {
32
        initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
33
        currency2 = deployMintAndApproveCurrency();
34
        router = new ActionsRouter(manager);
35
    }
36

                            
                        
37
    function test_sync_balanceIsZero() public noIsolate {
38
        assertEq(currency2.balanceOf(address(manager)), uint256(0));
39
        manager.sync(currency2);
40
        uint256 balance = currency2.balanceOf(address(manager));
41

                            
                        
42
        assertEq(uint256(balance), 0);
43
        assertEq(manager.getSyncedReserves(), 0);
44
    }
45

                            
                        
46
    function test_sync_balanceIsNonZero() public noIsolate {
47
        uint256 currency0Balance = currency0.balanceOf(address(manager));
48
        assertGt(currency0Balance, uint256(0));
49

                            
                        
50
        // Without calling sync, getReserves should return 0.
51
        assertEq(manager.getSyncedReserves(), 0);
52

                            
                        
53
        manager.sync(currency0);
54
        uint256 balance = currency0.balanceOf(address(manager));
55
        assertEq(balance, currency0Balance, "balance not equal");
56
        assertEq(manager.getSyncedReserves(), balance);
57
    }
58

                            
                        
59
    function test_settle_withStartingBalance() public noIsolate {
60
        assertGt(currency0.balanceOf(address(manager)), uint256(0));
61

                            
                        
62
        PoolSwapTest.TestSettings memory testSettings =
63
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
64

                            
                        
65
        // Sync has not been called.
66
        assertEq(manager.getSyncedReserves(), 0);
67

                            
                        
68
        swapRouter.swap(key, SWAP_PARAMS, testSettings, new bytes(0));
69
        (uint256 balanceCurrency0) = currency0.balanceOf(address(manager));
70
        manager.sync(currency0);
71
        assertEq(manager.getSyncedReserves(), balanceCurrency0); // Reserves are up to date since settle + sync was called.
72
    }
73

                            
                        
74
    function test_settle_withNoStartingBalance() public noIsolate {
75
        assertEq(currency2.balanceOf(address(manager)), uint256(0));
76

                            
                        
77
        (Currency cur0, Currency cur1) = currency0 < currency2 ? (currency0, currency2) : (currency2, currency0);
78
        PoolKey memory key2 =
79
            PoolKey({currency0: cur0, currency1: cur1, fee: 3000, tickSpacing: 60, hooks: IHooks(address(0))});
80

                            
                        
81
        manager.initialize(key2, SQRT_PRICE_1_1, new bytes(0));
82

                            
                        
83
        // Sync has not been called.
84
        assertEq(manager.getSyncedReserves(), 0);
85
        modifyLiquidityRouter.modifyLiquidity(key2, IPoolManager.ModifyLiquidityParams(-60, 60, 100, 0), new bytes(0));
86
        (uint256 balanceCurrency2) = currency2.balanceOf(address(manager));
87
        manager.sync(currency2);
88
        assertEq(manager.getSyncedReserves(), balanceCurrency2);
89
    }
90

                            
                        
91
    function test_settle_payOnBehalf(address taker, uint256 amount) public {
92
        vm.assume(taker != address(router));
93
        amount = bound(amount, 1, uint256(int256(type(int128).max)));
94
        MockERC20(Currency.unwrap(currency2)).approve(address(router), type(uint256).max);
95
        MockERC20(Currency.unwrap(currency2)).mint(address(manager), amount);
96

                            
                        
97
        Actions[] memory actions = new Actions[](6);
98
        bytes[] memory params = new bytes[](6);
99

                            
                        
100
        actions[0] = Actions.PRANK_TAKE_FROM;
101
        params[0] = abi.encode(currency2, taker, taker, amount);
102

                            
                        
103
        actions[1] = Actions.ASSERT_DELTA_EQUALS;
104
        params[1] = abi.encode(currency2, taker, int256(amount) * -1);
105

                            
                        
106
        actions[2] = Actions.SYNC;
107
        params[2] = abi.encode(currency2);
108

                            
                        
109
        actions[3] = Actions.TRANSFER_FROM;
110
        params[3] = abi.encode(currency2, address(this), address(manager), amount);
111

                            
                        
112
        actions[4] = Actions.SETTLE_FOR;
113
        params[4] = abi.encode(taker);
114

                            
                        
115
        actions[5] = Actions.ASSERT_DELTA_EQUALS;
116
        params[5] = abi.encode(currency2, taker, 0);
117

                            
                        
118
        router.executeActions(actions, params);
119
    }
120

                            
                        
121
    /// @notice When there is no balance and reserves are set to 0, no delta should be applied.
122
    function test_settle_noBalanceInPool_shouldNotApplyDelta() public noIsolate {
123
        assertEq(currency2.balanceOf(address(manager)), uint256(0));
124

                            
                        
125
        manager.sync(currency2);
126
        assertEq(manager.getSyncedReserves(), 0);
127

                            
                        
128
        Actions[] memory actions = new Actions[](2);
129
        bytes[] memory params = new bytes[](2);
130

                            
                        
131
        actions[0] = Actions.SETTLE;
132

                            
                        
133
        actions[1] = Actions.ASSERT_DELTA_EQUALS;
134
        params[1] = abi.encode(currency2, address(router), 0);
135

                            
                        
136
        router.executeActions(actions, params);
137
    }
138

                            
                        
139
    /// @notice When there is a balance, no delta should be applied.
140
    function test_settle_balanceInPool_shouldNotApplyDelta() public noIsolate {
141
        uint256 currency0Balance = currency0.balanceOf(address(manager));
142

                            
                        
143
        // Sync has not been called.
144
        assertEq(manager.getSyncedReserves(), 0);
145

                            
                        
146
        manager.sync(currency0);
147
        assertEq(manager.getSyncedReserves(), currency0Balance);
148

                            
                        
149
        Actions[] memory actions = new Actions[](2);
150
        bytes[] memory params = new bytes[](2);
151

                            
                        
152
        actions[0] = Actions.SETTLE;
153

                            
                        
154
        actions[1] = Actions.ASSERT_DELTA_EQUALS;
155
        params[1] = abi.encode(currency0, address(router), 0);
156

                            
                        
157
        router.executeActions(actions, params);
158
    }
159

                            
                        
160
    // @notice This tests expected behavior if you DO NOT call sync before a non native settle. (ie. Do not interact with the pool manager properly. You can lose funds.)
161
    function test_settle_nonNative_withoutSync_loseFunds() public noIsolate {
162
        MockERC20(Currency.unwrap(currency0)).approve(address(router), type(uint256).max);
163
        uint256 managerCurrency0BalanceBefore = currency0.balanceOf(address(manager));
164
        uint256 userCurrency0BalanceBefore = currency0.balanceOf(address(this));
165

                            
                        
166
        Actions[] memory actions = new Actions[](9);
167
        bytes[] memory params = new bytes[](9);
168

                            
                        
169
        manager.sync(currency0);
170
        snapStart("getReserves");
171
        uint256 reserves = manager.getSyncedReserves();
172
        snapEnd();
173
        assertEq(reserves, managerCurrency0BalanceBefore); // reserves are 100.
174

                            
                        
175
        actions[0] = Actions.TAKE;
176
        params[0] = abi.encode(currency0, address(this), 10);
177

                            
                        
178
        // Assert that the delta open on the router is -10. (The user owes 10 to the pool).
179
        actions[1] = Actions.ASSERT_DELTA_EQUALS;
180
        params[1] = abi.encode(currency0, address(router), -10);
181

                            
                        
182
        actions[2] = Actions.TRANSFER_FROM; // NOT syned before sending tokens
183
        params[2] = abi.encode(currency0, address(this), manager, 10);
184

                            
                        
185
        actions[3] = Actions.SETTLE; // calling settle without sync is expecting a native token, but msg.value == 0 so it settles for 0.
186

                            
                        
187
        actions[4] = Actions.ASSERT_DELTA_EQUALS;
188
        params[4] = abi.encode(currency0, address(router), -10);
189

                            
                        
190
        actions[5] = Actions.SYNC;
191
        params[5] = abi.encode(currency0);
192

                            
                        
193
        // To now settle the delta, the user owes 10 to the pool.
194
        actions[6] = Actions.TRANSFER_FROM;
195
        params[6] = abi.encode(currency0, address(this), manager, 10);
196

                            
                        
197
        actions[7] = Actions.SETTLE;
198

                            
                        
199
        actions[8] = Actions.ASSERT_DELTA_EQUALS;
200
        params[8] = abi.encode(currency0, address(router), 0);
201

                            
                        
202
        router.executeActions(actions, params);
203

                            
                        
204
        // The manager gained 10 currency0.
205
        assertEq(currency0.balanceOf(address(manager)), managerCurrency0BalanceBefore + 10);
206
        // The user lost 10 currency0, and can never claim it back.
207
        assertEq(currency0.balanceOf(address(this)), userCurrency0BalanceBefore - 10);
208
    }
209

                            
                        
210
    function test_settle_failsWithNativeERC20IfNotSyncedInOrder(uint256 value) public noIsolate {
211
        value = bound(value, 1, uint256(int256(type(int128).max / 2)));
212
        vm.deal(address(this), value);
213
        vm.deal(address(manager), value);
214
        NativeERC20 nativeERC20 = new NativeERC20();
215

                            
                        
216
        manager.sync(Currency.wrap(address(nativeERC20)));
217

                            
                        
218
        Actions[] memory actions = new Actions[](1);
219
        bytes[] memory params = new bytes[](1);
220

                            
                        
221
        // Revert with NonZeroNativeValue
222
        actions[0] = Actions.SETTLE_NATIVE;
223
        params[0] = abi.encode(value);
224

                            
                        
225
        vm.expectRevert(IPoolManager.NonZeroNativeValue.selector);
226
        router.executeActions{value: value}(actions, params);
227

                            
                        
228
        // Reference only - see OZ C01 report - previous test confirming vulnerability
229
        // uint256 balanceBefore = address(this).balance;
230

                            
                        
231
        // actions[1] = Actions.SETTLE;
232
        // params[1] = abi.encode(Currency.wrap(address(nativeERC20)));
233

                            
                        
234
        // actions[2] = Actions.ASSERT_DELTA_EQUALS;
235
        // params[2] = abi.encode(Currency.wrap(address(0)), address(router), value);
236

                            
                        
237
        // actions[3] = Actions.ASSERT_DELTA_EQUALS;
238
        // params[3] = abi.encode(Currency.wrap(address(nativeERC20)), address(router), value);
239

                            
                        
240
        // actions[4] = Actions.TAKE;
241
        // params[4] = abi.encode(Currency.wrap(address(0)), address(this), value);
242

                            
                        
243
        // actions[5] = Actions.TAKE;
244
        // params[5] = abi.encode(Currency.wrap(address(nativeERC20)), address(this), value);
245

                            
                        
246
        // uint256 balanceAfter = address(this).balance;
247
        // assertEq(balanceAfter - balanceBefore, value);
248
    }
249
}
250

                            
                        

Lines covered: 0 / 214 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {stdError} from "forge-std/StdError.sol";
6
import {GasSnapshot} from "../lib/forge-gas-snapshot/src/GasSnapshot.sol";
7
import {Constants} from "./utils/Constants.sol";
8
import {Pool} from "../src/libraries/Pool.sol";
9
import {TickMath} from "../src/libraries/TickMath.sol";
10

                            
                        
11
contract LiquidityMathRef {
12
    function addDelta(uint128 x, int128 y) external pure returns (uint128) {
13
        return y < 0 ? x - uint128(-y) : x + uint128(y);
14
    }
15

                            
                        
16
    function addDelta(bool upper, int128 liquidityNetBefore, int128 liquidityDelta)
17
        external
18
        pure
19
        returns (int128 liquidityNet)
20
    {
21
        liquidityNet = upper ? liquidityNetBefore - liquidityDelta : liquidityNetBefore + liquidityDelta;
22
    }
23
}
24

                            
                        
25
contract TickTest is Test, GasSnapshot {
26
    using Pool for Pool.State;
27

                            
                        
28
    int24 constant LOW_TICK_SPACING = 10;
29
    int24 constant MEDIUM_TICK_SPACING = 60;
30
    int24 constant HIGH_TICK_SPACING = 200;
31

                            
                        
32
    Pool.State public pool;
33

                            
                        
34
    LiquidityMathRef internal liquidityMath;
35

                            
                        
36
    function setUp() public {
37
        liquidityMath = new LiquidityMathRef();
38
    }
39

                            
                        
40
    function ticks(int24 tick) internal view returns (Pool.TickInfo memory) {
41
        return pool.ticks[tick];
42
    }
43

                            
                        
44
    function tickBitmap(int16 word) internal view returns (uint256) {
45
        return pool.tickBitmap[word];
46
    }
47

                            
                        
48
    function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) internal pure returns (uint128) {
49
        return Pool.tickSpacingToMaxLiquidityPerTick(tickSpacing);
50
    }
51

                            
                        
52
    function setTick(int24 tick, Pool.TickInfo memory info) internal {
53
        pool.ticks[tick] = info;
54
    }
55

                            
                        
56
    function setTickBitmap(int16 word, uint256 bitmap) internal {
57
        pool.tickBitmap[word] = bitmap;
58
    }
59

                            
                        
60
    function getFeeGrowthInside(
61
        int24 tickLower,
62
        int24 tickUpper,
63
        int24 tickCurrent,
64
        uint256 feeGrowthGlobal0X128,
65
        uint256 feeGrowthGlobal1X128
66
    ) internal returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) {
67
        pool.slot0 = pool.slot0.setTick(tickCurrent);
68
        pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128;
69
        pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128;
70
        return pool.getFeeGrowthInside(tickLower, tickUpper);
71
    }
72

                            
                        
73
    function update(
74
        int24 tick,
75
        int24 tickCurrent,
76
        int128 liquidityDelta,
77
        uint256 feeGrowthGlobal0X128,
78
        uint256 feeGrowthGlobal1X128,
79
        bool upper
80
    ) internal returns (bool flipped, uint128 liquidityGrossAfter) {
81
        pool.slot0 = pool.slot0.setTick(tickCurrent);
82
        pool.feeGrowthGlobal0X128 = feeGrowthGlobal0X128;
83
        pool.feeGrowthGlobal1X128 = feeGrowthGlobal1X128;
84
        return pool.updateTick(tick, liquidityDelta, upper);
85
    }
86

                            
                        
87
    function clear(int24 tick) internal {
88
        pool.clearTick(tick);
89
    }
90

                            
                        
91
    function cross(int24 tick, uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128)
92
        internal
93
        returns (int128 liquidityNet)
94
    {
95
        return pool.crossTick(tick, feeGrowthGlobal0X128, feeGrowthGlobal1X128);
96
    }
97

                            
                        
98
    function getMinTick(int24 tickSpacing) internal pure returns (int256) {
99
        return (TickMath.MIN_TICK / tickSpacing) * tickSpacing;
100
    }
101

                            
                        
102
    function getMaxTick(int24 tickSpacing) internal pure returns (int256) {
103
        return (TickMath.MAX_TICK / tickSpacing) * tickSpacing;
104
    }
105

                            
                        
106
    function checkCantOverflow(int24 tickSpacing, uint128 maxLiquidityPerTick) internal pure {
107
        assertLe(
108
            uint256(
109
                uint256(maxLiquidityPerTick)
110
                    * uint256((getMaxTick(tickSpacing) - getMinTick(tickSpacing)) / tickSpacing + 1)
111
            ),
112
            uint256(Constants.MAX_UINT128)
113
        );
114
    }
115

                            
                        
116
    function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForLowFee() public pure {
117
        uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(LOW_TICK_SPACING);
118

                            
                        
119
        assertEq(maxLiquidityPerTick, 1917569901783203986719870431555990);
120
        checkCantOverflow(LOW_TICK_SPACING, maxLiquidityPerTick);
121
    }
122

                            
                        
123
    function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForMediumFee() public pure {
124
        uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(MEDIUM_TICK_SPACING);
125

                            
                        
126
        assertEq(maxLiquidityPerTick, 11505743598341114571880798222544994);
127
        checkCantOverflow(MEDIUM_TICK_SPACING, maxLiquidityPerTick);
128
    }
129

                            
                        
130
    function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForHighFee() public pure {
131
        uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(HIGH_TICK_SPACING);
132

                            
                        
133
        assertEq(maxLiquidityPerTick, 38350317471085141830651933667504588);
134
        checkCantOverflow(HIGH_TICK_SPACING, maxLiquidityPerTick);
135
    }
136

                            
                        
137
    function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForMinTickSpacing() public pure {
138
        uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(TickMath.MIN_TICK_SPACING);
139

                            
                        
140
        assertEq(maxLiquidityPerTick, 191757530477355301479181766273477);
141
        checkCantOverflow(TickMath.MIN_TICK_SPACING, maxLiquidityPerTick);
142
    }
143

                            
                        
144
    function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForMaxTickSpacing() public pure {
145
        uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(TickMath.MAX_TICK_SPACING);
146

                            
                        
147
        assertEq(maxLiquidityPerTick, 6186952125835244790243174680577603844);
148
        checkCantOverflow(TickMath.MAX_TICK_SPACING, maxLiquidityPerTick);
149
    }
150

                            
                        
151
    function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueForEntireRange() public pure {
152
        uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(TickMath.MAX_TICK);
153

                            
                        
154
        assertEq(maxLiquidityPerTick, type(uint128).max / 3);
155
        checkCantOverflow(TickMath.MAX_TICK, maxLiquidityPerTick);
156
    }
157

                            
                        
158
    function testTick_tickSpacingToMaxLiquidityPerTick_returnsTheCorrectValueFor2302() public pure {
159
        uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(2302);
160

                            
                        
161
        assertEq(maxLiquidityPerTick, 441351967472034323558203122479595605);
162
        checkCantOverflow(2302, maxLiquidityPerTick);
163
    }
164

                            
                        
165
    function testTick_tickSpacingToMaxLiquidityPerTick_gasCostMinTickSpacing() public {
166
        snapStart("tickSpacingToMaxLiquidityPerTick_gasCostMinTickSpacing");
167
        tickSpacingToMaxLiquidityPerTick(TickMath.MIN_TICK_SPACING);
168
        snapEnd();
169
    }
170

                            
                        
171
    function testTick_tickSpacingToMaxLiquidityPerTick_gasCost60TickSpacing() public {
172
        snapStart("tickSpacingToMaxLiquidityPerTick_gasCost60TickSpacing");
173
        tickSpacingToMaxLiquidityPerTick(60);
174
        snapEnd();
175
    }
176

                            
                        
177
    function testTick_tickSpacingToMaxLiquidityPerTick_gasCostMaxTickSpacing() public {
178
        snapStart("tickSpacingToMaxLiquidityPerTick_gasCostMaxTickSpacing");
179
        tickSpacingToMaxLiquidityPerTick(TickMath.MAX_TICK_SPACING);
180
        snapEnd();
181
    }
182

                            
                        
183
    function testTick_getFeeGrowthInside_returnsAllForTwoUninitializedTicksIfTickIsInside() public {
184
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15);
185

                            
                        
186
        assertEq(feeGrowthInside0X128, 15);
187
        assertEq(feeGrowthInside1X128, 15);
188
    }
189

                            
                        
190
    function testTick_getFeeGrowthInside_returns0ForTwoUninitializedTicksIfTickIsAbove() public {
191
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 4, 15, 15);
192

                            
                        
193
        assertEq(feeGrowthInside0X128, 0);
194
        assertEq(feeGrowthInside1X128, 0);
195
    }
196

                            
                        
197
    function testTick_getFeeGrowthInside_returns0ForTwoUninitializedTicksIfTickIsBelow() public {
198
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, -4, 15, 15);
199

                            
                        
200
        assertEq(feeGrowthInside0X128, 0);
201
        assertEq(feeGrowthInside1X128, 0);
202
    }
203

                            
                        
204
    function testTick_getFeeGrowthInside_subtractsUpperTickIfBelow() public {
205
        Pool.TickInfo memory info;
206

                            
                        
207
        info.feeGrowthOutside0X128 = 2;
208
        info.feeGrowthOutside1X128 = 3;
209
        info.liquidityGross = 0;
210
        info.liquidityNet = 0;
211

                            
                        
212
        setTick(2, info);
213

                            
                        
214
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15);
215

                            
                        
216
        assertEq(feeGrowthInside0X128, 13);
217
        assertEq(feeGrowthInside1X128, 12);
218
    }
219

                            
                        
220
    function testTick_getFeeGrowthInside_subtractsLowerTickIfAbove() public {
221
        Pool.TickInfo memory info;
222

                            
                        
223
        info.feeGrowthOutside0X128 = 2;
224
        info.feeGrowthOutside1X128 = 3;
225
        info.liquidityGross = 0;
226
        info.liquidityNet = 0;
227

                            
                        
228
        setTick(-2, info);
229

                            
                        
230
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15);
231

                            
                        
232
        assertEq(feeGrowthInside0X128, 13);
233
        assertEq(feeGrowthInside1X128, 12);
234
    }
235

                            
                        
236
    function testTick_getFeeGrowthInside_subtractsUpperAndLowerTickIfInside() public {
237
        Pool.TickInfo memory info;
238

                            
                        
239
        info.feeGrowthOutside0X128 = 2;
240
        info.feeGrowthOutside1X128 = 3;
241
        info.liquidityGross = 0;
242
        info.liquidityNet = 0;
243

                            
                        
244
        setTick(-2, info);
245

                            
                        
246
        info.feeGrowthOutside0X128 = 4;
247
        info.feeGrowthOutside1X128 = 1;
248
        info.liquidityGross = 0;
249
        info.liquidityNet = 0;
250

                            
                        
251
        setTick(2, info);
252

                            
                        
253
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15);
254

                            
                        
255
        assertEq(feeGrowthInside0X128, 9);
256
        assertEq(feeGrowthInside1X128, 11);
257
    }
258

                            
                        
259
    function testTick_getFeeGrowthInside_worksCorrectlyWithOverflowOnInsideTick() public {
260
        Pool.TickInfo memory info;
261

                            
                        
262
        info.feeGrowthOutside0X128 = Constants.MAX_UINT256 - 3;
263
        info.feeGrowthOutside1X128 = Constants.MAX_UINT256 - 2;
264
        info.liquidityGross = 0;
265
        info.liquidityNet = 0;
266

                            
                        
267
        setTick(-2, info);
268

                            
                        
269
        info.feeGrowthOutside0X128 = 3;
270
        info.feeGrowthOutside1X128 = 5;
271
        info.liquidityGross = 0;
272
        info.liquidityNet = 0;
273

                            
                        
274
        setTick(2, info);
275

                            
                        
276
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(-2, 2, 0, 15, 15);
277

                            
                        
278
        assertEq(feeGrowthInside0X128, 16);
279
        assertEq(feeGrowthInside1X128, 13);
280
    }
281

                            
                        
282
    function testTick_update_flipsFromZeroToNonzero() public {
283
        (bool flipped, uint128 liquidityGrossAfter) = update(0, 0, 1, 0, 0, false);
284

                            
                        
285
        assertEq(flipped, true);
286
        assertEq(liquidityGrossAfter, 1);
287
    }
288

                            
                        
289
    function testTick_update_doesNotFlipFromNonzeroToGreaterNonzero() public {
290
        update(0, 0, 1, 0, 0, false);
291
        (bool flipped, uint128 liquidityGrossAfter) = update(0, 0, 1, 0, 0, false);
292

                            
                        
293
        assertEq(flipped, false);
294
        assertEq(liquidityGrossAfter, 2);
295
    }
296

                            
                        
297
    function testTick_update_flipsFromNonzeroToZero() public {
298
        update(0, 0, 1, 0, 0, false);
299
        (bool flipped, uint128 liquidityGrossAfter) = update(0, 0, -1, 0, 0, false);
300

                            
                        
301
        assertEq(flipped, true);
302
        assertEq(liquidityGrossAfter, 0);
303
    }
304

                            
                        
305
    function testTick_update_doesNotFlipFromNonzeroToLesserZero() public {
306
        update(0, 0, 2, 0, 0, false);
307
        (bool flipped, uint128 liquidityGrossAfter) = update(0, 0, -1, 0, 0, false);
308

                            
                        
309
        assertEq(flipped, false);
310
        assertEq(liquidityGrossAfter, 1);
311
    }
312

                            
                        
313
    function testTick_update_netsTheLiquidityBasedOnUpperFlag() public {
314
        Pool.TickInfo memory tickInfo;
315

                            
                        
316
        update(0, 0, 2, 0, 0, false);
317
        update(0, 0, 1, 0, 0, true);
318
        update(0, 0, 3, 0, 0, true);
319
        update(0, 0, 1, 0, 0, false);
320
        tickInfo = ticks(0);
321

                            
                        
322
        assertEq(tickInfo.liquidityGross, 2 + 1 + 3 + 1);
323
        assertEq(tickInfo.liquidityNet, 2 - 1 - 3 + 1);
324
    }
325

                            
                        
326
    function testTick_update_revertsOnOverflowLiquidityGross() public {
327
        update(0, 0, int128(Constants.MAX_UINT128 / 2 - 1), 0, 0, false);
328

                            
                        
329
        vm.expectRevert();
330
        update(0, 0, int128(Constants.MAX_UINT128 / 2 - 1), 0, 0, false);
331
    }
332

                            
                        
333
    function testTick_update_assumesAllGrowthHappensBelowTicksLteCurrentTick() public {
334
        Pool.TickInfo memory tickInfo;
335

                            
                        
336
        update(1, 1, 1, 1, 2, false);
337
        tickInfo = ticks(1);
338

                            
                        
339
        assertEq(tickInfo.feeGrowthOutside0X128, 1);
340
        assertEq(tickInfo.feeGrowthOutside1X128, 2);
341
    }
342

                            
                        
343
    function testTick_update_doesNotSetAnyGrowthFieldsIfTickIsAlreadyInitialized() public {
344
        Pool.TickInfo memory tickInfo;
345

                            
                        
346
        update(1, 1, 1, 1, 2, false);
347
        update(1, 1, 1, 6, 7, false);
348
        tickInfo = ticks(1);
349

                            
                        
350
        assertEq(tickInfo.feeGrowthOutside0X128, 1);
351
        assertEq(tickInfo.feeGrowthOutside1X128, 2);
352
    }
353

                            
                        
354
    function testTick_update_doesNotSetAnyGrowthFieldsForTicksGtCurrentTick() public {
355
        Pool.TickInfo memory tickInfo;
356

                            
                        
357
        update(2, 1, 1, 1, 2, false);
358
        tickInfo = ticks(2);
359

                            
                        
360
        assertEq(tickInfo.feeGrowthOutside0X128, 0);
361
        assertEq(tickInfo.feeGrowthOutside1X128, 0);
362
    }
363

                            
                        
364
    function testTick_update_liquidityParsing_parsesMaxUint128StoredLiquidityGrossBeforeUpdate() public {
365
        Pool.TickInfo memory info;
366

                            
                        
367
        info.feeGrowthOutside0X128 = 0;
368
        info.feeGrowthOutside1X128 = 0;
369
        info.liquidityGross = Constants.MAX_UINT128;
370
        info.liquidityNet = 0;
371

                            
                        
372
        setTick(2, info);
373
        update(2, 1, -1, 1, 2, false);
374

                            
                        
375
        info = ticks(2);
376

                            
                        
377
        assertEq(info.liquidityGross, Constants.MAX_UINT128 - 1);
378
        assertEq(info.liquidityNet, -1);
379
    }
380

                            
                        
381
    function testTick_update_liquidityParsing_parsesMaxUint128StoredLiquidityGrossAfterUpdate() public {
382
        Pool.TickInfo memory info;
383

                            
                        
384
        info.feeGrowthOutside0X128 = 0;
385
        info.feeGrowthOutside1X128 = 0;
386
        info.liquidityGross = (Constants.MAX_UINT128 / 2) + 1;
387
        info.liquidityNet = 0;
388

                            
                        
389
        setTick(2, info);
390

                            
                        
391
        update(2, 1, int128(Constants.MAX_UINT128 / 2), 1, 2, false);
392

                            
                        
393
        info = ticks(2);
394

                            
                        
395
        assertEq(info.liquidityGross, Constants.MAX_UINT128);
396
        assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2));
397
    }
398

                            
                        
399
    function testTick_update_liquidityParsing_parsesMaxInt128StoredLiquidityGrossBeforeUpdate() public {
400
        Pool.TickInfo memory info;
401

                            
                        
402
        info.feeGrowthOutside0X128 = 0;
403
        info.feeGrowthOutside1X128 = 0;
404
        info.liquidityGross = 1;
405
        info.liquidityNet = int128(Constants.MAX_UINT128 / 2);
406

                            
                        
407
        setTick(2, info);
408
        update(2, 1, -1, 1, 2, false);
409

                            
                        
410
        info = ticks(2);
411

                            
                        
412
        assertEq(info.liquidityGross, 0);
413
        assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2 - 1));
414
    }
415

                            
                        
416
    function testTick_update_liquidityParsing_parsesMaxInt128StoredLiquidityGrossAfterUpdate() public {
417
        Pool.TickInfo memory info;
418

                            
                        
419
        info.feeGrowthOutside0X128 = 0;
420
        info.feeGrowthOutside1X128 = 0;
421
        info.liquidityGross = 0;
422
        info.liquidityNet = int128(Constants.MAX_UINT128 / 2 - 1);
423

                            
                        
424
        setTick(2, info);
425

                            
                        
426
        update(2, 1, 1, 1, 2, false);
427

                            
                        
428
        info = ticks(2);
429

                            
                        
430
        assertEq(info.liquidityGross, 1);
431
        assertEq(info.liquidityNet, int128(Constants.MAX_UINT128 / 2));
432
    }
433

                            
                        
434
    function testTick_update_fuzz(uint128 liquidityGross, int128 liquidityNet, int128 liquidityDelta, bool upper)
435
        public
436
    {
437
        try liquidityMath.addDelta(liquidityGross, liquidityDelta) returns (uint128 liquidityGrossAfter) {
438
            try liquidityMath.addDelta(upper, liquidityNet, liquidityDelta) returns (int128 liquidityNetAfter) {
439
                Pool.TickInfo memory info = Pool.TickInfo({
440
                    liquidityGross: liquidityGross,
441
                    liquidityNet: liquidityNet,
442
                    feeGrowthOutside0X128: 0,
443
                    feeGrowthOutside1X128: 0
444
                });
445

                            
                        
446
                setTick(2, info);
447
                update({
448
                    tick: 2,
449
                    tickCurrent: 1,
450
                    liquidityDelta: liquidityDelta,
451
                    feeGrowthGlobal0X128: 0,
452
                    feeGrowthGlobal1X128: 0,
453
                    upper: upper
454
                });
455

                            
                        
456
                info = ticks(2);
457

                            
                        
458
                assertEq(info.liquidityGross, liquidityGrossAfter);
459
                assertEq(info.liquidityNet, liquidityNetAfter);
460
            } catch (bytes memory reason) {
461
                assertEq(reason, stdError.arithmeticError);
462
            }
463
        } catch (bytes memory reason) {
464
            assertEq(reason, stdError.arithmeticError);
465
        }
466
    }
467

                            
                        
468
    function testTick_clear_deletesAllTheDataInTheTick() public {
469
        Pool.TickInfo memory info;
470

                            
                        
471
        info.feeGrowthOutside0X128 = 1;
472
        info.feeGrowthOutside1X128 = 2;
473
        info.liquidityGross = 3;
474
        info.liquidityNet = 4;
475

                            
                        
476
        setTick(2, info);
477

                            
                        
478
        clear(2);
479

                            
                        
480
        info = ticks(2);
481

                            
                        
482
        assertEq(info.feeGrowthOutside0X128, 0);
483
        assertEq(info.feeGrowthOutside1X128, 0);
484
        assertEq(info.liquidityGross, 0);
485
        assertEq(info.liquidityNet, 0);
486
    }
487

                            
                        
488
    function testTick_cross_flipsTheGrowthVariables() public {
489
        Pool.TickInfo memory info;
490

                            
                        
491
        info.feeGrowthOutside0X128 = 1;
492
        info.feeGrowthOutside1X128 = 2;
493
        info.liquidityGross = 3;
494
        info.liquidityNet = 4;
495

                            
                        
496
        setTick(2, info);
497

                            
                        
498
        cross(2, 7, 9);
499

                            
                        
500
        info = ticks(2);
501

                            
                        
502
        assertEq(info.feeGrowthOutside0X128, 6);
503
        assertEq(info.feeGrowthOutside1X128, 7);
504
    }
505

                            
                        
506
    function testTick_cross_twoFlipsAreNoOp() public {
507
        Pool.TickInfo memory info;
508

                            
                        
509
        info.feeGrowthOutside0X128 = 1;
510
        info.feeGrowthOutside1X128 = 2;
511
        info.liquidityGross = 3;
512
        info.liquidityNet = 4;
513

                            
                        
514
        setTick(2, info);
515

                            
                        
516
        cross(2, 7, 9);
517
        cross(2, 7, 9);
518

                            
                        
519
        info = ticks(2);
520

                            
                        
521
        assertEq(info.feeGrowthOutside0X128, 1);
522
        assertEq(info.feeGrowthOutside1X128, 2);
523
    }
524

                            
                        
525
    function test_getPoolTickInfo(int24 tick, Pool.TickInfo memory info) public {
526
        setTick(tick, info);
527
        Pool.TickInfo memory actualInfo = ticks(tick);
528
        assertEq(actualInfo.liquidityGross, info.liquidityGross);
529
        assertEq(actualInfo.liquidityNet, info.liquidityNet);
530
        assertEq(actualInfo.feeGrowthOutside0X128, info.feeGrowthOutside0X128);
531
        assertEq(actualInfo.feeGrowthOutside1X128, info.feeGrowthOutside1X128);
532
    }
533

                            
                        
534
    function test_getPoolBitmapInfo(int16 word, uint256 bitmap) public {
535
        setTickBitmap(word, bitmap);
536
        assertEq(tickBitmap(word), bitmap);
537
    }
538

                            
                        
539
    function testTick_tickSpacingToParametersInvariants_fuzz(int24 tickSpacing) public pure {
540
        tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING));
541

                            
                        
542
        int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing;
543
        int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing;
544

                            
                        
545
        uint128 maxLiquidityPerTick = Pool.tickSpacingToMaxLiquidityPerTick(tickSpacing);
546

                            
                        
547
        // symmetry around 0 tick
548
        assertEq(maxTick, -minTick);
549
        // positive max tick
550
        assertGt(maxTick, 0);
551
        // divisibility
552
        assertEq((maxTick - minTick) % tickSpacing, 0);
553

                            
                        
554
        uint256 numTicks = uint256(int256((maxTick - minTick) / tickSpacing)) + 1;
555

                            
                        
556
        // sum of max liquidity on each tick is at most the cap
557
        assertGe(type(uint128).max, uint256(maxLiquidityPerTick) * numTicks);
558
    }
559
}
560

                            
                        

Lines covered: 0 / 55 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
5
import {Test} from "forge-std/Test.sol";
6
import {BitMath} from "../../src/libraries/BitMath.sol";
7

                            
                        
8
contract TestBitMath is Test, GasSnapshot {
9
    function test_mostSignificantBit_revertsWhenZero() public {
10
        vm.expectRevert();
11
        BitMath.mostSignificantBit(0);
12
    }
13

                            
                        
14
    function test_mostSignificantBit_one() public pure {
15
        assertEq(BitMath.mostSignificantBit(1), 0);
16
    }
17

                            
                        
18
    function test_mostSignificantBit_two() public pure {
19
        assertEq(BitMath.mostSignificantBit(2), 1);
20
    }
21

                            
                        
22
    function test_mostSignificantBit_powersOfTwo() public pure {
23
        for (uint256 i = 0; i < 255; i++) {
24
            uint256 x = 1 << i;
25
            assertEq(BitMath.mostSignificantBit(x), i);
26
        }
27
    }
28

                            
                        
29
    function test_mostSignificantBit_maxUint256() public pure {
30
        assertEq(BitMath.mostSignificantBit(type(uint256).max), 255);
31
    }
32

                            
                        
33
    function test_fuzz_mostSignificantBit(uint256 x) public pure {
34
        vm.assume(x != 0);
35
        assertEq(BitMath.mostSignificantBit(x), mostSignificantBitReference(x));
36
    }
37

                            
                        
38
    function test_invariant_mostSignificantBit(uint256 x) public pure {
39
        vm.assume(x != 0);
40
        uint8 msb = BitMath.mostSignificantBit(x);
41
        assertGe(x, uint256(2) ** msb);
42
        assertTrue(msb == 255 || x < uint256(2) ** (msb + 1));
43
    }
44

                            
                        
45
    function test_mostSignificantBit_gas() public {
46
        snapStart("BitMathMostSignificantBitSmallNumber");
47
        BitMath.mostSignificantBit(3568);
48
        snapEnd();
49

                            
                        
50
        snapStart("BitMathMostSignificantBitMaxUint128");
51
        BitMath.mostSignificantBit(type(uint128).max);
52
        snapEnd();
53

                            
                        
54
        snapStart("BitMathMostSignificantBitMaxUint256");
55
        BitMath.mostSignificantBit(type(uint256).max);
56
        snapEnd();
57
    }
58

                            
                        
59
    function test_leastSignificantBit_revertsWhenZero() public {
60
        vm.expectRevert();
61
        BitMath.leastSignificantBit(0);
62
    }
63

                            
                        
64
    function test_leastSignificantBit_one() public pure {
65
        assertEq(BitMath.leastSignificantBit(1), 0);
66
    }
67

                            
                        
68
    function test_leastSignificantBit_two() public pure {
69
        assertEq(BitMath.leastSignificantBit(2), 1);
70
    }
71

                            
                        
72
    function test_leastSignificantBit_powersOfTwo() public pure {
73
        for (uint256 i = 0; i < 255; i++) {
74
            uint256 x = 1 << i;
75
            assertEq(BitMath.leastSignificantBit(x), i);
76
        }
77
    }
78

                            
                        
79
    function test_leastSignificantBit_maxUint256() public pure {
80
        assertEq(BitMath.leastSignificantBit(type(uint256).max), 0);
81
    }
82

                            
                        
83
    function test_fuzz_leastSignificantBit(uint256 x) public pure {
84
        vm.assume(x != 0);
85
        assertEq(BitMath.leastSignificantBit(x), leastSignificantBitReference(x));
86
    }
87

                            
                        
88
    function test_invariant_leastSignificantBit(uint256 x) public pure {
89
        vm.assume(x != 0);
90
        uint8 lsb = BitMath.leastSignificantBit(x);
91
        assertNotEq(x & (uint256(2) ** lsb), 0);
92
        assertEq(x & (uint256(2) ** lsb - 1), 0);
93
    }
94

                            
                        
95
    function test_leastSignificantBit_gas() public {
96
        snapStart("BitMathLeastSignificantBitSmallNumber");
97
        BitMath.leastSignificantBit(3568);
98
        snapEnd();
99

                            
                        
100
        snapStart("BitMathLeastSignificantBitMaxUint128");
101
        BitMath.leastSignificantBit(type(uint128).max);
102
        snapEnd();
103

                            
                        
104
        snapStart("BitMathLeastSignificantBitMaxUint256");
105
        BitMath.leastSignificantBit(type(uint256).max);
106
        snapEnd();
107
    }
108

                            
                        
109
    function mostSignificantBitReference(uint256 x) private pure returns (uint256) {
110
        uint256 i = 0;
111
        while ((x >>= 1) > 0) {
112
            ++i;
113
        }
114
        return i;
115
    }
116

                            
                        
117
    function leastSignificantBitReference(uint256 x) private pure returns (uint256) {
118
        require(x > 0, "BitMath: zero has no least significant bit");
119

                            
                        
120
        uint256 i = 0;
121
        while ((x >> i) & 1 == 0) {
122
            ++i;
123
        }
124
        return i;
125
    }
126
}
127

                            
                        

Lines covered: 0 / 97 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.19;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {FullMath} from "../../src/libraries/FullMath.sol";
6

                            
                        
7
contract FullMathTest is Test {
8
    using FullMath for uint256;
9

                            
                        
10
    uint256 constant Q128 = 2 ** 128;
11
    uint256 constant MAX_UINT256 = type(uint256).max;
12

                            
                        
13
    function test_fuzz_mulDiv_revertsWith0Denominator(uint256 x, uint256 y) public {
14
        vm.expectRevert();
15
        x.mulDiv(y, 0);
16
    }
17

                            
                        
18
    function test_mulDiv_revertsWithOverflowingNumeratorAndZeroDenominator() public {
19
        vm.expectRevert();
20
        Q128.mulDiv(Q128, 0);
21
    }
22

                            
                        
23
    function test_mulDiv_revertsIfOutputOverflows() public {
24
        vm.expectRevert();
25
        Q128.mulDiv(Q128, 1);
26
    }
27

                            
                        
28
    function test_mulDiv_revertsOverflowWithAllMaxInputs() public {
29
        vm.expectRevert();
30
        MAX_UINT256.mulDiv(MAX_UINT256, MAX_UINT256 - 1);
31
    }
32

                            
                        
33
    function test_mulDiv_validAllMaxInputs() public pure {
34
        assertEq(MAX_UINT256.mulDiv(MAX_UINT256, MAX_UINT256), MAX_UINT256);
35
    }
36

                            
                        
37
    function test_mulDiv_validWithoutPhantomOverflow() public pure {
38
        uint256 result = Q128 / 3;
39
        assertEq(Q128.mulDiv(50 * Q128 / 100, 150 * Q128 / 100), result);
40
    }
41

                            
                        
42
    function test_mulDiv_validWithPhantomOverflow() public pure {
43
        uint256 result = 4375 * Q128 / 1000;
44
        assertEq(Q128.mulDiv(35 * Q128, 8 * Q128), result);
45
    }
46

                            
                        
47
    function test_mulDiv_phantomOverflowRepeatingDecimal() public pure {
48
        uint256 result = 1 * Q128 / 3;
49
        assertEq(Q128.mulDiv(1000 * Q128, 3000 * Q128), result);
50
    }
51

                            
                        
52
    function test_fuzz_mulDiv(uint256 x, uint256 y, uint256 d) public pure {
53
        vm.assume(d != 0);
54
        vm.assume(y != 0);
55
        x = bound(x, 0, type(uint256).max / y);
56
        assertEq(FullMath.mulDiv(x, y, d), x * y / d);
57
    }
58

                            
                        
59
    function test_fuzz_mulDivRoundingUp_revertsWith0Denominator(uint256 x, uint256 y) public {
60
        vm.expectRevert();
61
        x.mulDivRoundingUp(y, 0);
62
    }
63

                            
                        
64
    function test_mulDivRoundingUp_validWithAllMaxInputs() public pure {
65
        assertEq(MAX_UINT256.mulDivRoundingUp(MAX_UINT256, MAX_UINT256), MAX_UINT256);
66
    }
67

                            
                        
68
    function test_mulDivRoundingUp_validWithNoPhantomOverflow() public pure {
69
        uint256 result = Q128 / 3 + 1;
70
        assertEq(Q128.mulDivRoundingUp(50 * Q128 / 100, 150 * Q128 / 100), result);
71
    }
72

                            
                        
73
    function test_mulDivRoundingUp_validWithPhantomOverflow() public pure {
74
        uint256 result = 4375 * Q128 / 1000;
75
        assertEq(Q128.mulDiv(35 * Q128, 8 * Q128), result);
76
    }
77

                            
                        
78
    function test_mulDivRoundingUp_validWithPhantomOverflowRepeatingDecimal() public pure {
79
        uint256 result = 1 * Q128 / 3 + 1;
80
        assertEq(Q128.mulDivRoundingUp(1000 * Q128, 3000 * Q128), result);
81
    }
82

                            
                        
83
    function test_mulDivRoundingUp_revertsIfMulDivOverflows256BitsAfterRoundingUp() public {
84
        vm.expectRevert();
85
        FullMath.mulDivRoundingUp(535006138814359, 432862656469423142931042426214547535783388063929571229938474969, 2);
86
    }
87

                            
                        
88
    function test_mulDivRoundingUp_revertsIfMulDivOverflows256BitsAfterRoundingUpCase2() public {
89
        vm.expectRevert();
90
        FullMath.mulDivRoundingUp(
91
            115792089237316195423570985008687907853269984659341747863450311749907997002549,
92
            115792089237316195423570985008687907853269984659341747863450311749907997002550,
93
            115792089237316195423570985008687907853269984653042931687443039491902864365164
94
        );
95
    }
96

                            
                        
97
    function test_fuzz_mulDivRoundingUp(uint256 x, uint256 y, uint256 d) public pure {
98
        vm.assume(d != 0);
99
        vm.assume(y != 0);
100
        x = bound(x, 0, type(uint256).max / y);
101
        uint256 numerator = x * y;
102
        uint256 result = FullMath.mulDivRoundingUp(x, y, d);
103
        if (mulmod(x, y, d) > 0) {
104
            assertEq(result, numerator / d + 1);
105
        } else {
106
            assertEq(result, numerator / d);
107
        }
108
    }
109

                            
                        
110
    function test_invariant_mulDivRounding(uint256 x, uint256 y, uint256 d) public pure {
111
        unchecked {
112
            vm.assume(d > 0);
113
            vm.assume(!resultOverflows(x, y, d));
114

                            
                        
115
            uint256 ceiled = FullMath.mulDivRoundingUp(x, y, d);
116

                            
                        
117
            uint256 floored = FullMath.mulDiv(x, y, d);
118

                            
                        
119
            if (mulmod(x, y, d) > 0) {
120
                assertEq(ceiled - floored, 1);
121
            } else {
122
                assertEq(ceiled, floored);
123
            }
124
        }
125
    }
126

                            
                        
127
    function test_invariant_mulDiv(uint256 x, uint256 y, uint256 d) public pure {
128
        unchecked {
129
            vm.assume(d > 0);
130
            vm.assume(!resultOverflows(x, y, d));
131
            uint256 z = FullMath.mulDiv(x, y, d);
132
            if (x == 0 || y == 0) {
133
                assertEq(z, 0);
134
                return;
135
            }
136

                            
                        
137
            // recompute x and y via mulDiv of the result of floor(x*y/d), should always be less than original inputs by < d
138
            uint256 x2 = FullMath.mulDiv(z, d, y);
139
            uint256 y2 = FullMath.mulDiv(z, d, x);
140
            assertLe(x2, x);
141
            assertLe(y2, y);
142

                            
                        
143
            assertLt(x - x2, d);
144
            assertLt(y - y2, d);
145
        }
146
    }
147

                            
                        
148
    function test_invariant_mulDivRoundingUp(uint256 x, uint256 y, uint256 d) external pure {
149
        unchecked {
150
            vm.assume(d > 0);
151
            vm.assume(!resultOverflows(x, y, d));
152
            uint256 z = FullMath.mulDivRoundingUp(x, y, d);
153
            if (x == 0 || y == 0) {
154
                assertEq(z, 0);
155
                return;
156
            }
157

                            
                        
158
            vm.assume(!resultOverflows(z, d, y));
159
            vm.assume(!resultOverflows(z, d, x));
160
            // recompute x and y via mulDiv of the result of ceil(x*y/d), should always be greater than original inputs by < d
161
            uint256 x2 = FullMath.mulDiv(z, d, y);
162
            uint256 y2 = FullMath.mulDiv(z, d, x);
163
            assertGe(x2, x);
164
            assertGe(y2, y);
165

                            
                        
166
            assertLt(x2 - x, d);
167
            assertLt(y2 - y, d);
168
        }
169
    }
170

                            
                        
171
    function test_resultOverflows_helper() public pure {
172
        assertFalse(resultOverflows(0, 0, 1));
173
        assertFalse(resultOverflows(1, 0, 1));
174
        assertFalse(resultOverflows(0, 1, 1));
175
        assertFalse(resultOverflows(1, 1, 1));
176
        assertFalse(resultOverflows(10000000, 10000000, 1));
177
        assertFalse(resultOverflows(Q128, 50 * Q128 / 100, 150 * Q128 / 100));
178
        assertFalse(resultOverflows(Q128, 35 * Q128, 8 * Q128));
179
        assertTrue(resultOverflows(type(uint256).max, type(uint256).max, type(uint256).max - 1));
180
        assertTrue(resultOverflows(Q128, type(uint256).max, 1));
181
    }
182

                            
                        
183
    function resultOverflows(uint256 x, uint256 y, uint256 d) private pure returns (bool) {
184
        require(d > 0);
185

                            
                        
186
        // If x or y is zero, the result will be zero, and there's no overflow
187
        if (x == 0 || y == 0) {
188
            return false;
189
        }
190

                            
                        
191
        // If intermediate multiplication doesn't overflow, there's no overflow
192
        if (x <= type(uint256).max / y) return false;
193

                            
                        
194
        uint256 remainder = mulmod(x, y, type(uint256).max);
195
        uint256 small;
196
        uint256 big;
197
        unchecked {
198
            small = x * y;
199
            big = (remainder - small) - (remainder < small ? 1 : 0);
200
        }
201

                            
                        
202
        bool mulDivResultOverflows = d <= big;
203
        bool mulDivRoundingUpResultOverflows = mulDivResultOverflows;
204

                            
                        
205
        // must catch edgecase where mulDiv doesn't overflow but roundingUp does
206
        if (!mulDivResultOverflows) {
207
            mulDivRoundingUpResultOverflows = FullMath.mulDiv(x, y, d) == type(uint256).max;
208
        }
209

                            
                        
210
        return mulDivResultOverflows || mulDivRoundingUpResultOverflows;
211
    }
212
}
213

                            
                        

Lines covered: 0 / 317 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
5
import {Test} from "forge-std/Test.sol";
6
import {Vm} from "forge-std/Vm.sol";
7
import {Hooks} from "../../src/libraries/Hooks.sol";
8
import {LPFeeLibrary} from "../../src/libraries/LPFeeLibrary.sol";
9
import {MockHooks} from "../../src/test/MockHooks.sol";
10
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
11
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
12
import {IHooks} from "../../src/interfaces/IHooks.sol";
13
import {Currency} from "../../src/types/Currency.sol";
14
import {PoolManager} from "../../src/PoolManager.sol";
15
import {PoolSwapTest} from "../../src/test/PoolSwapTest.sol";
16
import {PoolDonateTest} from "../../src/test/PoolDonateTest.sol";
17
import {Deployers} from "test/utils/Deployers.sol";
18
import {ProtocolFees} from "../../src/ProtocolFees.sol";
19
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
20
import {PoolKey} from "../../src/types/PoolKey.sol";
21
import {IERC20Minimal} from "../../src/interfaces/external/IERC20Minimal.sol";
22
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
23
import {BaseTestHooks} from "../../src/test/BaseTestHooks.sol";
24
import {EmptyRevertContract} from "../../src/test/EmptyRevertContract.sol";
25
import {StateLibrary} from "../../src/libraries/StateLibrary.sol";
26
import {Constants} from "../utils/Constants.sol";
27

                            
                        
28
contract HooksTest is Test, Deployers, GasSnapshot {
29
    using PoolIdLibrary for PoolKey;
30
    using Hooks for IHooks;
31
    using StateLibrary for IPoolManager;
32

                            
                        
33
    MockHooks mockHooks;
34
    BaseTestHooks revertingHookImpl;
35

                            
                        
36
    function setUp() public {
37
        MockHooks impl = new MockHooks();
38
        vm.etch(Constants.ALL_HOOKS, address(impl).code);
39
        mockHooks = MockHooks(Constants.ALL_HOOKS);
40

                            
                        
41
        revertingHookImpl = new BaseTestHooks();
42

                            
                        
43
        initializeManagerRoutersAndPoolsWithLiq(mockHooks);
44
    }
45

                            
                        
46
    function test_initialize_succeedsWithHook() public {
47
        manager.initialize(uninitializedKey, SQRT_PRICE_1_1, new bytes(123));
48

                            
                        
49
        (uint160 sqrtPriceX96,,,) = manager.getSlot0(uninitializedKey.toId());
50
        assertEq(sqrtPriceX96, SQRT_PRICE_1_1);
51
        assertEq(mockHooks.beforeInitializeData(), new bytes(123));
52
        assertEq(mockHooks.afterInitializeData(), new bytes(123));
53
    }
54

                            
                        
55
    function test_beforeInitialize_invalidReturn() public {
56
        mockHooks.setReturnValue(mockHooks.beforeInitialize.selector, bytes4(0xdeadbeef));
57
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
58
        manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES);
59
    }
60

                            
                        
61
    function test_afterInitialize_invalidReturn() public {
62
        mockHooks.setReturnValue(mockHooks.afterInitialize.selector, bytes4(0xdeadbeef));
63
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
64
        manager.initialize(uninitializedKey, SQRT_PRICE_1_1, ZERO_BYTES);
65
    }
66

                            
                        
67
    function test_beforeAfterAddLiquidity_beforeAfterRemoveLiquidity_succeedsWithHook() public {
68
        MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18);
69
        MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18);
70
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 1e18, 0), new bytes(111));
71
        assertEq(mockHooks.beforeAddLiquidityData(), new bytes(111));
72
        assertEq(mockHooks.afterAddLiquidityData(), new bytes(111));
73

                            
                        
74
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, -1e18, 0), new bytes(222));
75
        assertEq(mockHooks.beforeRemoveLiquidityData(), new bytes(222));
76
        assertEq(mockHooks.afterRemoveLiquidityData(), new bytes(222));
77
    }
78

                            
                        
79
    function test_beforeAfterAddLiquidity_calledWithPositiveLiquidityDelta() public {
80
        MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18);
81
        MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18);
82
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 100, 0), new bytes(111));
83
        assertEq(mockHooks.beforeAddLiquidityData(), new bytes(111));
84
        assertEq(mockHooks.afterAddLiquidityData(), new bytes(111));
85
    }
86

                            
                        
87
    function test_beforeAfterRemoveLiquidity_calledWithZeroLiquidityDelta() public {
88
        MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18);
89
        MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18);
90
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 1e18, 0), new bytes(111));
91
        assertEq(mockHooks.beforeAddLiquidityData(), new bytes(111));
92
        assertEq(mockHooks.afterAddLiquidityData(), new bytes(111));
93

                            
                        
94
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 0, 0), new bytes(222));
95
        assertEq(mockHooks.beforeAddLiquidityData(), new bytes(111));
96
        assertEq(mockHooks.afterAddLiquidityData(), new bytes(111));
97
        assertEq(mockHooks.beforeRemoveLiquidityData(), new bytes(222));
98
        assertEq(mockHooks.afterRemoveLiquidityData(), new bytes(222));
99
    }
100

                            
                        
101
    function test_beforeAfterRemoveLiquidity_calledWithPositiveLiquidityDelta() public {
102
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, 1e18, 0), new bytes(111));
103
        MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18);
104
        MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18);
105
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(0, 60, -1e18, 0), new bytes(111));
106
        assertEq(mockHooks.beforeRemoveLiquidityData(), new bytes(111));
107
        assertEq(mockHooks.afterRemoveLiquidityData(), new bytes(111));
108
    }
109

                            
                        
110
    function test_beforeAddLiquidity_invalidReturn() public {
111
        mockHooks.setReturnValue(mockHooks.beforeAddLiquidity.selector, bytes4(0xdeadbeef));
112
        MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18);
113
        MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18);
114
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
115
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
116
    }
117

                            
                        
118
    function test_beforeRemoveLiquidity_invalidReturn() public {
119
        mockHooks.setReturnValue(mockHooks.beforeRemoveLiquidity.selector, bytes4(0xdeadbeef));
120
        MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18);
121
        MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18);
122
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
123
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
124
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
125
    }
126

                            
                        
127
    function test_afterAddLiquidity_invalidReturn() public {
128
        mockHooks.setReturnValue(mockHooks.afterAddLiquidity.selector, bytes4(0xdeadbeef));
129
        MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18);
130
        MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18);
131
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
132
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
133
    }
134

                            
                        
135
    function test_afterRemoveLiquidity_invalidReturn() public {
136
        mockHooks.setReturnValue(mockHooks.afterRemoveLiquidity.selector, bytes4(0xdeadbeef));
137
        MockERC20(Currency.unwrap(key.currency0)).mint(address(this), 1e18);
138
        MockERC20(Currency.unwrap(key.currency0)).approve(address(modifyLiquidityRouter), 1e18);
139
        modifyLiquidityRouter.modifyLiquidity(key, LIQUIDITY_PARAMS, ZERO_BYTES);
140
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
141
        modifyLiquidityRouter.modifyLiquidity(key, REMOVE_LIQUIDITY_PARAMS, ZERO_BYTES);
142
    }
143

                            
                        
144
    function test_swap_succeedsWithHook() public {
145
        IPoolManager.SwapParams memory swapParams =
146
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
147

                            
                        
148
        PoolSwapTest.TestSettings memory testSettings =
149
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
150

                            
                        
151
        swapRouter.swap(key, swapParams, testSettings, new bytes(222));
152
        assertEq(mockHooks.beforeSwapData(), new bytes(222));
153
        assertEq(mockHooks.afterSwapData(), new bytes(222));
154
    }
155

                            
                        
156
    function test_beforeSwap_invalidReturn() public {
157
        mockHooks.setReturnValue(mockHooks.beforeSwap.selector, bytes4(0xdeadbeef));
158
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
159
        swapRouter.swap(
160
            key,
161
            IPoolManager.SwapParams(false, 100, SQRT_PRICE_1_1 + 60),
162
            PoolSwapTest.TestSettings(true, true),
163
            ZERO_BYTES
164
        );
165
    }
166

                            
                        
167
    function test_afterSwap_invalidReturn() public {
168
        mockHooks.setReturnValue(mockHooks.afterSwap.selector, bytes4(0xdeadbeef));
169
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
170
        swapRouter.swap(
171
            key,
172
            IPoolManager.SwapParams(false, 100, SQRT_PRICE_1_1 + 60),
173
            PoolSwapTest.TestSettings(true, true),
174
            ZERO_BYTES
175
        );
176
    }
177

                            
                        
178
    function test_donate_succeedsWithHook() public {
179
        donateRouter.donate(key, 100, 200, new bytes(333));
180
        assertEq(mockHooks.beforeDonateData(), new bytes(333));
181
        assertEq(mockHooks.afterDonateData(), new bytes(333));
182
    }
183

                            
                        
184
    function test_beforeDonate_invalidReturn() public {
185
        mockHooks.setReturnValue(mockHooks.beforeDonate.selector, bytes4(0xdeadbeef));
186
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
187
        donateRouter.donate(key, 100, 200, ZERO_BYTES);
188
    }
189

                            
                        
190
    function test_afterDonate_invalidReturn() public {
191
        mockHooks.setReturnValue(mockHooks.beforeDonate.selector, bytes4(0xdeadbeef));
192
        vm.expectRevert(Hooks.InvalidHookResponse.selector);
193
        donateRouter.donate(key, 100, 200, ZERO_BYTES);
194
    }
195

                            
                        
196
    // hook validation
197
    function test_fuzz_validateHookPermissions_noHooks(uint160 addr) public view {
198
        uint160 preAddr = addr & clearAllHookPermissionsMask;
199

                            
                        
200
        IHooks hookAddr = IHooks(address(preAddr));
201
        Hooks.validateHookPermissions(
202
            hookAddr,
203
            Hooks.Permissions({
204
                beforeInitialize: false,
205
                afterInitialize: false,
206
                beforeAddLiquidity: false,
207
                afterAddLiquidity: false,
208
                beforeRemoveLiquidity: false,
209
                afterRemoveLiquidity: false,
210
                beforeSwap: false,
211
                afterSwap: false,
212
                beforeDonate: false,
213
                afterDonate: false,
214
                beforeSwapReturnDelta: false,
215
                afterSwapReturnDelta: false,
216
                afterAddLiquidityReturnDelta: false,
217
                afterRemoveLiquidityReturnDelta: false
218
            })
219
        );
220
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
221
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
222
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
223
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
224
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
225
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
226
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
227
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
228
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
229
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
230
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
231
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
232
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
233
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
234
    }
235

                            
                        
236
    function test_fuzz_validateHookPermissions_beforeInitialize(uint160 addr) public view {
237
        uint160 preAddr = addr & clearAllHookPermissionsMask;
238

                            
                        
239
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_INITIALIZE_FLAG)));
240
        Hooks.validateHookPermissions(
241
            hookAddr,
242
            Hooks.Permissions({
243
                beforeInitialize: true,
244
                afterInitialize: false,
245
                beforeAddLiquidity: false,
246
                afterAddLiquidity: false,
247
                beforeRemoveLiquidity: false,
248
                afterRemoveLiquidity: false,
249
                beforeSwap: false,
250
                afterSwap: false,
251
                beforeDonate: false,
252
                afterDonate: false,
253
                beforeSwapReturnDelta: false,
254
                afterSwapReturnDelta: false,
255
                afterAddLiquidityReturnDelta: false,
256
                afterRemoveLiquidityReturnDelta: false
257
            })
258
        );
259
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
260
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
261
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
262
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
263
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
264
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
265
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
266
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
267
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
268
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
269
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
270
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
271
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
272
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
273
    }
274

                            
                        
275
    function test_fuzz_validateHookPermissions_afterInitialize(uint160 addr) public view {
276
        uint160 preAddr = addr & clearAllHookPermissionsMask;
277

                            
                        
278
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_INITIALIZE_FLAG)));
279
        Hooks.validateHookPermissions(
280
            hookAddr,
281
            Hooks.Permissions({
282
                beforeInitialize: false,
283
                afterInitialize: true,
284
                beforeAddLiquidity: false,
285
                afterAddLiquidity: false,
286
                beforeRemoveLiquidity: false,
287
                afterRemoveLiquidity: false,
288
                beforeSwap: false,
289
                afterSwap: false,
290
                beforeDonate: false,
291
                afterDonate: false,
292
                beforeSwapReturnDelta: false,
293
                afterSwapReturnDelta: false,
294
                afterAddLiquidityReturnDelta: false,
295
                afterRemoveLiquidityReturnDelta: false
296
            })
297
        );
298
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
299
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
300
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
301
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
302
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
303
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
304
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
305
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
306
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
307
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
308
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
309
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
310
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
311
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
312
    }
313

                            
                        
314
    function test_fuzz_validateHookPermissions_beforeAndAfterInitialize(uint160 addr) public view {
315
        uint160 preAddr = addr & clearAllHookPermissionsMask;
316
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_INITIALIZE_FLAG)));
317
        Hooks.validateHookPermissions(
318
            hookAddr,
319
            Hooks.Permissions({
320
                beforeInitialize: true,
321
                afterInitialize: true,
322
                beforeAddLiquidity: false,
323
                afterAddLiquidity: false,
324
                beforeRemoveLiquidity: false,
325
                afterRemoveLiquidity: false,
326
                beforeSwap: false,
327
                afterSwap: false,
328
                beforeDonate: false,
329
                afterDonate: false,
330
                beforeSwapReturnDelta: false,
331
                afterSwapReturnDelta: false,
332
                afterAddLiquidityReturnDelta: false,
333
                afterRemoveLiquidityReturnDelta: false
334
            })
335
        );
336
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
337
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
338
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
339
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
340
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
341
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
342
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
343
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
344
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
345
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
346
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
347
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
348
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
349
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
350
    }
351

                            
                        
352
    function test_fuzz_validateHookPermissions_beforeAddLiquidity(uint160 addr) public view {
353
        uint160 preAddr = addr & clearAllHookPermissionsMask;
354
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_ADD_LIQUIDITY_FLAG)));
355
        Hooks.validateHookPermissions(
356
            hookAddr,
357
            Hooks.Permissions({
358
                beforeInitialize: false,
359
                afterInitialize: false,
360
                beforeAddLiquidity: true,
361
                afterAddLiquidity: false,
362
                beforeRemoveLiquidity: false,
363
                afterRemoveLiquidity: false,
364
                beforeSwap: false,
365
                afterSwap: false,
366
                beforeDonate: false,
367
                afterDonate: false,
368
                beforeSwapReturnDelta: false,
369
                afterSwapReturnDelta: false,
370
                afterAddLiquidityReturnDelta: false,
371
                afterRemoveLiquidityReturnDelta: false
372
            })
373
        );
374
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
375
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
376
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
377
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
378
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
379
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
380
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
381
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
382
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
383
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
384
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
385
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
386
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
387
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
388
    }
389

                            
                        
390
    function test_fuzz_validateHookPermissions_afterAddLiquidity(uint160 addr) public view {
391
        uint160 preAddr = addr & clearAllHookPermissionsMask;
392
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_ADD_LIQUIDITY_FLAG)));
393
        Hooks.validateHookPermissions(
394
            hookAddr,
395
            Hooks.Permissions({
396
                beforeInitialize: false,
397
                afterInitialize: false,
398
                beforeAddLiquidity: false,
399
                afterAddLiquidity: true,
400
                beforeRemoveLiquidity: false,
401
                afterRemoveLiquidity: false,
402
                beforeSwap: false,
403
                afterSwap: false,
404
                beforeDonate: false,
405
                afterDonate: false,
406
                beforeSwapReturnDelta: false,
407
                afterSwapReturnDelta: false,
408
                afterAddLiquidityReturnDelta: false,
409
                afterRemoveLiquidityReturnDelta: false
410
            })
411
        );
412
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
413
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
414
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
415
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
416
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
417
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
418
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
419
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
420
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
421
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
422
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
423
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
424
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
425
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
426
    }
427

                            
                        
428
    function test_fuzz_validateHookPermissions_beforeAndAfterAddLiquidity(uint160 addr) public view {
429
        uint160 preAddr = addr & clearAllHookPermissionsMask;
430
        IHooks hookAddr =
431
            IHooks(address(uint160(preAddr | Hooks.BEFORE_ADD_LIQUIDITY_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG)));
432
        Hooks.validateHookPermissions(
433
            hookAddr,
434
            Hooks.Permissions({
435
                beforeInitialize: false,
436
                afterInitialize: false,
437
                beforeAddLiquidity: true,
438
                afterAddLiquidity: true,
439
                beforeRemoveLiquidity: false,
440
                afterRemoveLiquidity: false,
441
                beforeSwap: false,
442
                afterSwap: false,
443
                beforeDonate: false,
444
                afterDonate: false,
445
                beforeSwapReturnDelta: false,
446
                afterSwapReturnDelta: false,
447
                afterAddLiquidityReturnDelta: false,
448
                afterRemoveLiquidityReturnDelta: false
449
            })
450
        );
451
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
452
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
453
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
454
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
455
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
456
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
457
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
458
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
459
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
460
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
461
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
462
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
463
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
464
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
465
    }
466

                            
                        
467
    function test_fuzz_validateHookPermissions_beforeRemoveLiquidity(uint160 addr) public view {
468
        uint160 preAddr = addr & clearAllHookPermissionsMask;
469
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG)));
470
        Hooks.validateHookPermissions(
471
            hookAddr,
472
            Hooks.Permissions({
473
                beforeInitialize: false,
474
                afterInitialize: false,
475
                beforeAddLiquidity: false,
476
                afterAddLiquidity: false,
477
                beforeRemoveLiquidity: true,
478
                afterRemoveLiquidity: false,
479
                beforeSwap: false,
480
                afterSwap: false,
481
                beforeDonate: false,
482
                afterDonate: false,
483
                beforeSwapReturnDelta: false,
484
                afterSwapReturnDelta: false,
485
                afterAddLiquidityReturnDelta: false,
486
                afterRemoveLiquidityReturnDelta: false
487
            })
488
        );
489
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
490
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
491
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
492
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
493
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
494
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
495
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
496
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
497
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
498
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
499
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
500
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
501
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
502
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
503
    }
504

                            
                        
505
    function test_fuzz_validateHookPermissions_afterRemoveLiquidity(uint160 addr) public view {
506
        uint160 preAddr = addr & clearAllHookPermissionsMask;
507
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)));
508
        Hooks.validateHookPermissions(
509
            hookAddr,
510
            Hooks.Permissions({
511
                beforeInitialize: false,
512
                afterInitialize: false,
513
                beforeAddLiquidity: false,
514
                afterAddLiquidity: false,
515
                beforeRemoveLiquidity: false,
516
                afterRemoveLiquidity: true,
517
                beforeSwap: false,
518
                afterSwap: false,
519
                beforeDonate: false,
520
                afterDonate: false,
521
                beforeSwapReturnDelta: false,
522
                afterSwapReturnDelta: false,
523
                afterAddLiquidityReturnDelta: false,
524
                afterRemoveLiquidityReturnDelta: false
525
            })
526
        );
527
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
528
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
529
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
530
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
531
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
532
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
533
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
534
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
535
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
536
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
537
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
538
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
539
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
540
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
541
    }
542

                            
                        
543
    function test_fuzz_validateHookPermissions_beforeAfterRemoveLiquidity(uint160 addr) public view {
544
        uint160 preAddr = addr & clearAllHookPermissionsMask;
545
        IHooks hookAddr =
546
            IHooks(address(uint160(preAddr | Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)));
547
        Hooks.validateHookPermissions(
548
            hookAddr,
549
            Hooks.Permissions({
550
                beforeInitialize: false,
551
                afterInitialize: false,
552
                beforeAddLiquidity: false,
553
                afterAddLiquidity: false,
554
                beforeRemoveLiquidity: true,
555
                afterRemoveLiquidity: true,
556
                beforeSwap: false,
557
                afterSwap: false,
558
                beforeDonate: false,
559
                afterDonate: false,
560
                beforeSwapReturnDelta: false,
561
                afterSwapReturnDelta: false,
562
                afterAddLiquidityReturnDelta: false,
563
                afterRemoveLiquidityReturnDelta: false
564
            })
565
        );
566
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
567
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
568
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
569
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
570
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
571
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
572
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
573
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
574
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
575
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
576
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
577
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
578
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
579
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
580
    }
581

                            
                        
582
    function test_fuzz_validateHookPermissions_beforeInitializeAfterAddLiquidity(uint160 addr) public view {
583
        uint160 preAddr = addr & clearAllHookPermissionsMask;
584
        IHooks hookAddr =
585
            IHooks(address(uint160(preAddr | Hooks.BEFORE_INITIALIZE_FLAG | Hooks.AFTER_ADD_LIQUIDITY_FLAG)));
586
        Hooks.validateHookPermissions(
587
            hookAddr,
588
            Hooks.Permissions({
589
                beforeInitialize: true,
590
                afterInitialize: false,
591
                beforeAddLiquidity: false,
592
                afterAddLiquidity: true,
593
                beforeRemoveLiquidity: false,
594
                afterRemoveLiquidity: false,
595
                beforeSwap: false,
596
                afterSwap: false,
597
                beforeDonate: false,
598
                afterDonate: false,
599
                beforeSwapReturnDelta: false,
600
                afterSwapReturnDelta: false,
601
                afterAddLiquidityReturnDelta: false,
602
                afterRemoveLiquidityReturnDelta: false
603
            })
604
        );
605
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
606
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
607
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
608
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
609
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
610
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
611
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
612
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
613
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
614
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
615
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
616
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
617
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
618
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
619
    }
620

                            
                        
621
    function test_fuzz_validateHookPermissions_beforeSwap(uint160 addr) public view {
622
        uint160 preAddr = addr & clearAllHookPermissionsMask;
623
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_SWAP_FLAG)));
624
        Hooks.validateHookPermissions(
625
            hookAddr,
626
            Hooks.Permissions({
627
                beforeInitialize: false,
628
                afterInitialize: false,
629
                beforeAddLiquidity: false,
630
                afterAddLiquidity: false,
631
                beforeRemoveLiquidity: false,
632
                afterRemoveLiquidity: false,
633
                beforeSwap: true,
634
                afterSwap: false,
635
                beforeDonate: false,
636
                afterDonate: false,
637
                beforeSwapReturnDelta: false,
638
                afterSwapReturnDelta: false,
639
                afterAddLiquidityReturnDelta: false,
640
                afterRemoveLiquidityReturnDelta: false
641
            })
642
        );
643
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
644
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
645
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
646
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
647
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
648
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
649
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
650
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
651
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
652
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
653
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
654
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
655
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
656
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
657
    }
658

                            
                        
659
    function test_fuzz_validateHookPermissions_afterSwap(uint160 addr) public view {
660
        uint160 preAddr = addr & clearAllHookPermissionsMask;
661
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_SWAP_FLAG)));
662
        Hooks.validateHookPermissions(
663
            hookAddr,
664
            Hooks.Permissions({
665
                beforeInitialize: false,
666
                afterInitialize: false,
667
                beforeAddLiquidity: false,
668
                afterAddLiquidity: false,
669
                beforeRemoveLiquidity: false,
670
                afterRemoveLiquidity: false,
671
                beforeSwap: false,
672
                afterSwap: true,
673
                beforeDonate: false,
674
                afterDonate: false,
675
                beforeSwapReturnDelta: false,
676
                afterSwapReturnDelta: false,
677
                afterAddLiquidityReturnDelta: false,
678
                afterRemoveLiquidityReturnDelta: false
679
            })
680
        );
681
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
682
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
683
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
684
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
685
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
686
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
687
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
688
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
689
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
690
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
691
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
692
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
693
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
694
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
695
    }
696

                            
                        
697
    function test_fuzz_validateHookPermissions_beforeAndAfterSwap(uint160 addr) public view {
698
        uint160 preAddr = addr & clearAllHookPermissionsMask;
699
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG)));
700
        Hooks.validateHookPermissions(
701
            hookAddr,
702
            Hooks.Permissions({
703
                beforeInitialize: false,
704
                afterInitialize: false,
705
                beforeAddLiquidity: false,
706
                afterAddLiquidity: false,
707
                beforeRemoveLiquidity: false,
708
                afterRemoveLiquidity: false,
709
                beforeSwap: true,
710
                afterSwap: true,
711
                beforeDonate: false,
712
                afterDonate: false,
713
                beforeSwapReturnDelta: false,
714
                afterSwapReturnDelta: false,
715
                afterAddLiquidityReturnDelta: false,
716
                afterRemoveLiquidityReturnDelta: false
717
            })
718
        );
719
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
720
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
721
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
722
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
723
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
724
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
725
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
726
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
727
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
728
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
729
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
730
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
731
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
732
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
733
    }
734

                            
                        
735
    function test_fuzz_validateHookPermissions_beforeDonate(uint160 addr) public view {
736
        uint160 preAddr = addr & clearAllHookPermissionsMask;
737
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_DONATE_FLAG)));
738
        Hooks.validateHookPermissions(
739
            hookAddr,
740
            Hooks.Permissions({
741
                beforeInitialize: false,
742
                afterInitialize: false,
743
                beforeAddLiquidity: false,
744
                afterAddLiquidity: false,
745
                beforeRemoveLiquidity: false,
746
                afterRemoveLiquidity: false,
747
                beforeSwap: false,
748
                afterSwap: false,
749
                beforeDonate: true,
750
                afterDonate: false,
751
                beforeSwapReturnDelta: false,
752
                afterSwapReturnDelta: false,
753
                afterAddLiquidityReturnDelta: false,
754
                afterRemoveLiquidityReturnDelta: false
755
            })
756
        );
757
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
758
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
759
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
760
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
761
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
762
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
763
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
764
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
765
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
766
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
767
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
768
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
769
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
770
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
771
    }
772

                            
                        
773
    function test_fuzz_validateHookPermissions_afterDonate(uint160 addr) public view {
774
        uint160 preAddr = addr & clearAllHookPermissionsMask;
775
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_DONATE_FLAG)));
776
        Hooks.validateHookPermissions(
777
            hookAddr,
778
            Hooks.Permissions({
779
                beforeInitialize: false,
780
                afterInitialize: false,
781
                beforeAddLiquidity: false,
782
                afterAddLiquidity: false,
783
                beforeRemoveLiquidity: false,
784
                afterRemoveLiquidity: false,
785
                beforeSwap: false,
786
                afterSwap: false,
787
                beforeDonate: false,
788
                afterDonate: true,
789
                beforeSwapReturnDelta: false,
790
                afterSwapReturnDelta: false,
791
                afterAddLiquidityReturnDelta: false,
792
                afterRemoveLiquidityReturnDelta: false
793
            })
794
        );
795
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
796
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
797
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
798
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
799
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
800
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
801
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
802
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
803
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
804
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
805
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
806
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
807
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
808
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
809
    }
810

                            
                        
811
    function test_fuzz_validateHookPermissions_beforeAndAfterDonate(uint160 addr) public view {
812
        uint160 preAddr = addr & clearAllHookPermissionsMask;
813
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_DONATE_FLAG | Hooks.AFTER_DONATE_FLAG)));
814
        Hooks.validateHookPermissions(
815
            hookAddr,
816
            Hooks.Permissions({
817
                beforeInitialize: false,
818
                afterInitialize: false,
819
                beforeAddLiquidity: false,
820
                afterAddLiquidity: false,
821
                beforeRemoveLiquidity: false,
822
                afterRemoveLiquidity: false,
823
                beforeSwap: false,
824
                afterSwap: false,
825
                beforeDonate: true,
826
                afterDonate: true,
827
                beforeSwapReturnDelta: false,
828
                afterSwapReturnDelta: false,
829
                afterAddLiquidityReturnDelta: false,
830
                afterRemoveLiquidityReturnDelta: false
831
            })
832
        );
833
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
834
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
835
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
836
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
837
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
838
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
839
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
840
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
841
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
842
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
843
        assertFalse(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
844
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
845
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
846
        assertFalse(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
847
    }
848

                            
                        
849
    function test_fuzz_validateHookPermissions_allHooks(uint160 addr) public view {
850
        uint160 preAddr = addr & clearAllHookPermissionsMask;
851
        uint160 allHookBitsFlipped = uint160((1 << hookPermissionCount) - 1);
852
        IHooks hookAddr = IHooks(address(uint160(preAddr) | allHookBitsFlipped));
853
        Hooks.validateHookPermissions(
854
            hookAddr,
855
            Hooks.Permissions({
856
                beforeInitialize: true,
857
                afterInitialize: true,
858
                beforeAddLiquidity: true,
859
                afterAddLiquidity: true,
860
                beforeRemoveLiquidity: true,
861
                afterRemoveLiquidity: true,
862
                beforeSwap: true,
863
                afterSwap: true,
864
                beforeDonate: true,
865
                afterDonate: true,
866
                beforeSwapReturnDelta: true,
867
                afterSwapReturnDelta: true,
868
                afterAddLiquidityReturnDelta: true,
869
                afterRemoveLiquidityReturnDelta: true
870
            })
871
        );
872
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_INITIALIZE_FLAG));
873
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_INITIALIZE_FLAG));
874
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_ADD_LIQUIDITY_FLAG));
875
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_FLAG));
876
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_REMOVE_LIQUIDITY_FLAG));
877
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_FLAG));
878
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_SWAP_FLAG));
879
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_SWAP_FLAG));
880
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_DONATE_FLAG));
881
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_DONATE_FLAG));
882
        assertTrue(hookAddr.hasPermission(Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG));
883
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG));
884
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG));
885
        assertTrue(hookAddr.hasPermission(Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG));
886
    }
887

                            
                        
888
    function test_fuzz_validateHookAddress_failsAllHooks(uint160 addr, uint16 mask) public {
889
        uint160 preAddr = addr & clearAllHookPermissionsMask;
890
        // Set the upper `hooksPermissionCount` number of bits to get the full mask in uint16.
891
        uint16 allHooksMask = uint16(~uint16(0));
892
        // We want any combination except all hooks.
893
        vm.assume(mask < (allHooksMask >> (16 - hookPermissionCount)));
894
        IHooks hookAddr = IHooks(address(uint160(preAddr) | uint160(mask)));
895
        vm.expectRevert(abi.encodeWithSelector(Hooks.HookAddressNotValid.selector, (address(hookAddr))));
896
        Hooks.validateHookPermissions(
897
            hookAddr,
898
            Hooks.Permissions({
899
                beforeInitialize: true,
900
                afterInitialize: true,
901
                beforeAddLiquidity: true,
902
                afterAddLiquidity: true,
903
                beforeRemoveLiquidity: true,
904
                afterRemoveLiquidity: true,
905
                beforeSwap: true,
906
                afterSwap: true,
907
                beforeDonate: true,
908
                afterDonate: true,
909
                beforeSwapReturnDelta: true,
910
                afterSwapReturnDelta: true,
911
                afterAddLiquidityReturnDelta: true,
912
                afterRemoveLiquidityReturnDelta: true
913
            })
914
        );
915
    }
916

                            
                        
917
    function test_fuzz_validateHookAddress_failsNoHooks(uint160 addr, uint16 mask) public {
918
        // we only want hookPermissionCount of mask
919
        mask = mask >> (16 - hookPermissionCount);
920
        uint160 preAddr = addr & clearAllHookPermissionsMask;
921
        // We want any combination except no hooks.
922
        vm.assume(mask != 0);
923
        IHooks hookAddr = IHooks(address(preAddr | uint160(mask)));
924
        vm.expectRevert(abi.encodeWithSelector(Hooks.HookAddressNotValid.selector, (address(hookAddr))));
925
        Hooks.validateHookPermissions(
926
            hookAddr,
927
            Hooks.Permissions({
928
                beforeInitialize: false,
929
                afterInitialize: false,
930
                beforeAddLiquidity: false,
931
                afterAddLiquidity: false,
932
                beforeRemoveLiquidity: false,
933
                afterRemoveLiquidity: false,
934
                beforeSwap: false,
935
                afterSwap: false,
936
                beforeDonate: false,
937
                afterDonate: false,
938
                beforeSwapReturnDelta: false,
939
                afterSwapReturnDelta: false,
940
                afterAddLiquidityReturnDelta: false,
941
                afterRemoveLiquidityReturnDelta: false
942
            })
943
        );
944
    }
945

                            
                        
946
    function test_isValidHookAddress_valid_anyFlags() public pure {
947
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000002000), 3000));
948
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000001000), 3000));
949
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000800), 3000));
950
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000400), 3000));
951
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000200), 3000));
952
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000100), 3000));
953
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000080), 3000));
954
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000040), 3000));
955
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000020), 3000));
956
        assertTrue(Hooks.isValidHookAddress(IHooks(0x0000000000000000000000000000000000000010), 3000));
957
        assertTrue(Hooks.isValidHookAddress(IHooks(0xF00040A85D5Af5BF1d1762f925BdAddc42013C00), 3000));
958
    }
959

                            
                        
960
    function test_isValidHookAddress_zeroAddress_fixedFee() public pure {
961
        assertTrue(Hooks.isValidHookAddress(IHooks(address(0)), 3000));
962
    }
963

                            
                        
964
    function testIsValidHookAddress_invalid_zeroAddressWithDynamicFee() public pure {
965
        assertFalse(Hooks.isValidHookAddress(IHooks(address(0)), LPFeeLibrary.DYNAMIC_FEE_FLAG));
966
    }
967

                            
                        
968
    function test_fuzz_isValidHookAddress_invalid_returnsDeltaWithoutHookFlag(uint160 addr) public view {
969
        uint160 preAddr = addr & clearAllHookPermissionsMask;
970
        IHooks hookAddr = IHooks(address(uint160(preAddr | Hooks.BEFORE_SWAP_RETURNS_DELTA_FLAG)));
971
        assertFalse(Hooks.isValidHookAddress(hookAddr, 3000));
972
        hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_SWAP_RETURNS_DELTA_FLAG)));
973
        assertFalse(Hooks.isValidHookAddress(hookAddr, 3000));
974
        hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)));
975
        assertFalse(Hooks.isValidHookAddress(hookAddr, 3000));
976
        hookAddr = IHooks(address(uint160(preAddr | Hooks.AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG)));
977
        assertFalse(Hooks.isValidHookAddress(hookAddr, 3000));
978
    }
979

                            
                        
980
    function test_isValidHookAddress_valid_noFlagsWithDynamicFee() public pure {
981
        assertTrue(
982
            Hooks.isValidHookAddress(IHooks(0x1000000000000000000000000000000000000000), LPFeeLibrary.DYNAMIC_FEE_FLAG)
983
        );
984
    }
985

                            
                        
986
    function test_isValidHookAddress_invalid_noFlagsNoDynamicFee() public pure {
987
        assertFalse(Hooks.isValidHookAddress(IHooks(0x1000000000000000000000000000000000000000), 3000));
988
        assertFalse(Hooks.isValidHookAddress(IHooks(0x0001000000000000000000000000000000004000), 3000));
989
        assertFalse(Hooks.isValidHookAddress(IHooks(0x003840A85D5AF5bf1D1762F925BDaDdc42010000), 3000));
990
        // not dynamic as another bit is dirty in the fee
991
        assertFalse(
992
            Hooks.isValidHookAddress(
993
                IHooks(0x1000000000000000000000000000000000000000), LPFeeLibrary.DYNAMIC_FEE_FLAG | uint24(3000)
994
            )
995
        );
996
    }
997

                            
                        
998
    function test_callHook_revertsWithBubbleUp() public {
999
        // This test executes _callHook through beforeSwap.
1000
        address beforeSwapFlag = address(uint160(Hooks.BEFORE_SWAP_FLAG));
1001
        vm.etch(beforeSwapFlag, address(revertingHookImpl).code);
1002
        BaseTestHooks revertingHook = BaseTestHooks(beforeSwapFlag);
1003

                            
                        
1004
        PoolKey memory key = PoolKey(currency0, currency1, 0, 60, IHooks(revertingHook));
1005
        manager.initialize(key, SQRT_PRICE_1_1, new bytes(0));
1006

                            
                        
1007
        IPoolManager.SwapParams memory swapParams =
1008
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
1009

                            
                        
1010
        PoolSwapTest.TestSettings memory testSettings =
1011
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
1012

                            
                        
1013
        vm.expectRevert(
1014
            abi.encodeWithSelector(
1015
                Hooks.FailedHookCall.selector, abi.encodeWithSelector(BaseTestHooks.HookNotImplemented.selector)
1016
            )
1017
        );
1018
        swapRouter.swap(key, swapParams, testSettings, new bytes(0));
1019
    }
1020

                            
                        
1021
    function test_callHook_revertsWithInternalErrorFailedHookCall() public {
1022
        // This test executes _callHook through beforeSwap.
1023
        EmptyRevertContract emptyRevertingHookImpl = new EmptyRevertContract();
1024
        address beforeSwapFlag = address(uint160(Hooks.BEFORE_SWAP_FLAG));
1025
        vm.etch(beforeSwapFlag, address(emptyRevertingHookImpl).code);
1026
        EmptyRevertContract revertingHook = EmptyRevertContract(beforeSwapFlag);
1027

                            
                        
1028
        PoolKey memory key = PoolKey(currency0, currency1, 0, 60, IHooks(address(revertingHook)));
1029
        manager.initialize(key, SQRT_PRICE_1_1, new bytes(0));
1030

                            
                        
1031
        IPoolManager.SwapParams memory swapParams =
1032
            IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
1033

                            
                        
1034
        PoolSwapTest.TestSettings memory testSettings =
1035
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false});
1036

                            
                        
1037
        vm.expectRevert(abi.encodeWithSelector(Hooks.FailedHookCall.selector, new bytes(0)));
1038
        swapRouter.swap(key, swapParams, testSettings, new bytes(0));
1039
    }
1040
}
1041

                            
                        

Lines covered: 0 / 37 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import "../../src/libraries/LPFeeLibrary.sol";
5
import "forge-std/Test.sol";
6

                            
                        
7
contract LPFeeLibraryTest is Test {
8
    function test_isDynamicFee_returnsTrue() public pure {
9
        uint24 dynamicFee = 0x800000;
10
        assertTrue(LPFeeLibrary.isDynamicFee(dynamicFee));
11
    }
12

                            
                        
13
    function test_isDynamicFee_returnsFalse_forOtherValues() public pure {
14
        uint24 dynamicFee = 0xFFFFFF;
15
        assertFalse(LPFeeLibrary.isDynamicFee(dynamicFee));
16
        dynamicFee = 0x7FFFFF;
17
        assertFalse(LPFeeLibrary.isDynamicFee(dynamicFee));
18
        dynamicFee = 0;
19
        assertFalse(LPFeeLibrary.isDynamicFee(dynamicFee));
20
        dynamicFee = 0x800001;
21
        assertFalse(LPFeeLibrary.isDynamicFee(dynamicFee));
22
    }
23

                            
                        
24
    function test_fuzz_isDynamicFee(uint24 fee) public pure {
25
        assertEq(fee == LPFeeLibrary.DYNAMIC_FEE_FLAG, LPFeeLibrary.isDynamicFee(fee));
26
    }
27

                            
                        
28
    function test_validate_doesNotRevertWithNoFee() public pure {
29
        uint24 fee = 0;
30
        LPFeeLibrary.validate(fee);
31
    }
32

                            
                        
33
    function test_validate_doesNotRevert() public pure {
34
        uint24 fee = 500000; // 50%
35
        LPFeeLibrary.validate(fee);
36
    }
37

                            
                        
38
    function test_validate_doesNotRevertWithMaxFee() public pure {
39
        uint24 maxFee = 1000000; // 100%
40
        LPFeeLibrary.validate(maxFee);
41
    }
42

                            
                        
43
    function test_validate_revertsWithLPFeeTooLarge() public {
44
        uint24 fee = 1000001;
45
        vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee));
46
        LPFeeLibrary.validate(fee);
47
    }
48

                            
                        
49
    function test_fuzz_validate(uint24 fee) public {
50
        if (fee > 1000000) {
51
            vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee));
52
        }
53
        LPFeeLibrary.validate(fee);
54
    }
55

                            
                        
56
    function test_getInitialLPFee_forStaticFeeIsCorrect() public pure {
57
        uint24 staticFee = 3000; // 30 bps
58
        assertEq(LPFeeLibrary.getInitialLPFee(staticFee), staticFee);
59
    }
60

                            
                        
61
    function test_getInitialLPFee_revertsWithLPFeeTooLarge_forStaticFee() public {
62
        uint24 staticFee = 1000001;
63
        vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, staticFee));
64
        LPFeeLibrary.getInitialLPFee(staticFee);
65
    }
66

                            
                        
67
    function test_getInitialLPFee_forDynamicFeeIsZero() public pure {
68
        uint24 dynamicFee = 0x800000;
69
        assertEq(LPFeeLibrary.getInitialLPFee(dynamicFee), 0);
70
    }
71

                            
                        
72
    function test_getInitialLpFee_revertsWithNonExactDynamicFee() public {
73
        uint24 dynamicFee = 0x800001;
74
        vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, dynamicFee));
75
        LPFeeLibrary.getInitialLPFee(dynamicFee);
76
    }
77

                            
                        
78
    function test_fuzz_getInitialLPFee(uint24 fee) public {
79
        if (fee == LPFeeLibrary.DYNAMIC_FEE_FLAG) {
80
            assertEq(LPFeeLibrary.getInitialLPFee(fee), 0);
81
        } else if (fee > 1000000) {
82
            vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, fee));
83
            LPFeeLibrary.getInitialLPFee(fee);
84
        } else {
85
            assertEq(LPFeeLibrary.getInitialLPFee(fee), fee);
86
        }
87
    }
88
}
89

                            
                        

Lines covered: 0 / 23 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {SafeCast} from "src/libraries/SafeCast.sol";
6
import {LiquidityMathTest as LiquidityMath} from "src/test/LiquidityMathTest.sol";
7

                            
                        
8
contract LiquidityMathRef {
9
    function addDelta(uint128 x, int128 y) external pure returns (uint128) {
10
        return y < 0 ? x - uint128(-y) : x + uint128(y);
11
    }
12
}
13

                            
                        
14
contract LiquidityMathTest is Test {
15
    LiquidityMath internal liquidityMath;
16
    LiquidityMathRef internal liquidityMathRef;
17

                            
                        
18
    function setUp() public {
19
        liquidityMath = new LiquidityMath();
20
        liquidityMathRef = new LiquidityMathRef();
21
    }
22

                            
                        
23
    /// @notice Test the revert reason for underflow
24
    function test_addDelta_throwsForUnderflow() public {
25
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
26
        liquidityMath.addDelta(0, -1);
27
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
28
        liquidityMath.addDelta(uint128(type(int128).max), type(int128).min);
29
    }
30

                            
                        
31
    /// @notice Test the revert reason for overflow
32
    function test_addDelta_throwsForOverflow() public {
33
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
34
        liquidityMath.addDelta(type(uint128).max, 1);
35
    }
36

                            
                        
37
    function test_addDelta_sub_int128min_throwsForReferenceOnly() public {
38
        assertEq(liquidityMath.addDelta(uint128(type(int128).min), type(int128).min), 0);
39
        vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x11));
40
        liquidityMathRef.addDelta(uint128(type(int128).min), type(int128).min);
41
    }
42

                            
                        
43
    function test_addDelta_sub_int128min_fuzz(uint128 x) public view {
44
        x = uint128(bound(x, uint128(type(int128).min), type(uint128).max));
45
        assertEq(liquidityMath.addDelta(x, type(int128).min), x - uint128(type(int128).min));
46
    }
47

                            
                        
48
    /// @notice Test the equivalence of the new `addDelta` and the reference implementation
49
    function test_addDelta_fuzz(uint128 x, int128 y) public {
50
        vm.assume(y != type(int128).min);
51
        try liquidityMath.addDelta(x, y) returns (uint128 z) {
52
            assertEq(z, liquidityMathRef.addDelta(x, y));
53
        } catch (bytes memory reason) {
54
            assertEq(bytes4(reason), SafeCast.SafeCastOverflow.selector);
55
            vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x11));
56
            liquidityMathRef.addDelta(x, y);
57
        }
58
    }
59
}
60

                            
                        

Lines covered: 0 / 7 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Lock} from "../../src/libraries/Lock.sol";
6

                            
                        
7
contract LockTest is Test {
8
    function test_lock() public {
9
        assertFalse(Lock.isUnlocked());
10

                            
                        
11
        Lock.unlock();
12

                            
                        
13
        assertTrue(Lock.isUnlocked());
14

                            
                        
15
        Lock.lock();
16

                            
                        
17
        assertFalse(Lock.isUnlocked());
18
    }
19

                            
                        
20
    function test_unlockedSlot() public pure {
21
        assertEq(bytes32(uint256(keccak256("Unlocked")) - 1), Lock.IS_UNLOCKED_SLOT);
22
    }
23
}
24

                            
                        

Lines covered: 0 / 19 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {NonZeroDeltaCount} from "../../src/libraries/NonZeroDeltaCount.sol";
6

                            
                        
7
contract NonZeroDeltaCountTest is Test {
8
    function test_incrementNonzeroDeltaCount() public {
9
        assertEq(NonZeroDeltaCount.read(), 0);
10
        NonZeroDeltaCount.increment();
11
        assertEq(NonZeroDeltaCount.read(), 1);
12
    }
13

                            
                        
14
    function test_decrementNonzeroDeltaCount() public {
15
        assertEq(NonZeroDeltaCount.read(), 0);
16
        NonZeroDeltaCount.increment();
17
        assertEq(NonZeroDeltaCount.read(), 1);
18
        NonZeroDeltaCount.decrement();
19
        assertEq(NonZeroDeltaCount.read(), 0);
20
    }
21

                            
                        
22
    // Reading from right to left. Bit of 0: call increase. Bit of 1: call decrease.
23
    // The library allows over over/underflow so we dont check for that here
24
    function test_fuzz_nonZeroDeltaCount(uint256 instructions) public {
25
        assertEq(NonZeroDeltaCount.read(), 0);
26
        uint256 expectedCount;
27
        for (uint256 i = 0; i < 256; i++) {
28
            if ((instructions & (1 << i)) == 0) {
29
                NonZeroDeltaCount.increment();
30
                unchecked {
31
                    expectedCount++;
32
                }
33
            } else {
34
                NonZeroDeltaCount.decrement();
35
                unchecked {
36
                    expectedCount--;
37
                }
38
            }
39
            assertEq(NonZeroDeltaCount.read(), expectedCount);
40
        }
41
    }
42

                            
                        
43
    function test_nonZeroDeltaCountSlot() public pure {
44
        assertEq(bytes32(uint256(keccak256("NonzeroDeltaCount")) - 1), NonZeroDeltaCount.NONZERO_DELTA_COUNT_SLOT);
45
    }
46
}
47

                            
                        

Lines covered: 0 / 85 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Vm} from "forge-std/Vm.sol";
6
import {Pool} from "../../src/libraries/Pool.sol";
7
import {PoolManager} from "../../src/PoolManager.sol";
8
import {Position} from "../../src/libraries/Position.sol";
9
import {TickMath} from "../../src/libraries/TickMath.sol";
10
import {TickBitmap} from "../../src/libraries/TickBitmap.sol";
11
import {LiquidityAmounts} from "../../test/utils/LiquidityAmounts.sol";
12
import {Constants} from "../../test/utils/Constants.sol";
13
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
14
import {Slot0} from "../../src/types/Slot0.sol";
15
import {SafeCast} from "../../src/libraries/SafeCast.sol";
16
import {ProtocolFeeLibrary} from "../../src/libraries/ProtocolFeeLibrary.sol";
17
import {LPFeeLibrary} from "../../src/libraries/LPFeeLibrary.sol";
18
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
19

                            
                        
20
contract PoolTest is Test, GasSnapshot {
21
    using Pool for Pool.State;
22
    using LPFeeLibrary for uint24;
23
    using ProtocolFeeLibrary for *;
24

                            
                        
25
    Pool.State state;
26

                            
                        
27
    uint24 constant MAX_PROTOCOL_FEE = ProtocolFeeLibrary.MAX_PROTOCOL_FEE; // 0.1%
28
    uint24 constant MAX_LP_FEE = LPFeeLibrary.MAX_LP_FEE; // 100%
29

                            
                        
30
    function testPoolInitialize(uint160 sqrtPriceX96, uint24 protocolFee, uint24 swapFee) public {
31
        if (sqrtPriceX96 < TickMath.MIN_SQRT_PRICE || sqrtPriceX96 >= TickMath.MAX_SQRT_PRICE) {
32
            vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96));
33
            state.initialize(sqrtPriceX96, protocolFee, swapFee);
34
        } else {
35
            state.initialize(sqrtPriceX96, protocolFee, swapFee);
36
            assertEq(state.slot0.sqrtPriceX96(), sqrtPriceX96);
37
            assertEq(state.slot0.protocolFee(), protocolFee);
38
            assertEq(state.slot0.tick(), TickMath.getTickAtSqrtPrice(sqrtPriceX96));
39
            assertLt(state.slot0.tick(), TickMath.MAX_TICK);
40
            assertGt(state.slot0.tick(), TickMath.MIN_TICK - 1);
41
        }
42
    }
43

                            
                        
44
    function testModifyLiquidity(
45
        uint160 sqrtPriceX96,
46
        uint24 protocolFee,
47
        uint24 lpFee,
48
        Pool.ModifyLiquidityParams memory params
49
    ) public {
50
        // Assumptions tested in PoolManager.t.sol
51
        params.tickSpacing = int24(bound(params.tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING));
52

                            
                        
53
        testPoolInitialize(sqrtPriceX96, protocolFee, lpFee);
54

                            
                        
55
        if (params.tickLower >= params.tickUpper) {
56
            vm.expectRevert(abi.encodeWithSelector(Pool.TicksMisordered.selector, params.tickLower, params.tickUpper));
57
        } else if (params.tickLower < TickMath.MIN_TICK) {
58
            vm.expectRevert(abi.encodeWithSelector(Pool.TickLowerOutOfBounds.selector, params.tickLower));
59
        } else if (params.tickUpper > TickMath.MAX_TICK) {
60
            vm.expectRevert(abi.encodeWithSelector(Pool.TickUpperOutOfBounds.selector, params.tickUpper));
61
        } else if (params.liquidityDelta < 0) {
62
            vm.expectRevert(SafeCast.SafeCastOverflow.selector);
63
        } else if (params.liquidityDelta == 0) {
64
            vm.expectRevert(Position.CannotUpdateEmptyPosition.selector);
65
        } else if (params.liquidityDelta > int128(Pool.tickSpacingToMaxLiquidityPerTick(params.tickSpacing))) {
66
            vm.expectRevert(abi.encodeWithSelector(Pool.TickLiquidityOverflow.selector, params.tickLower));
67
        } else if (params.tickLower % params.tickSpacing != 0) {
68
            vm.expectRevert(
69
                abi.encodeWithSelector(TickBitmap.TickMisaligned.selector, params.tickLower, params.tickSpacing)
70
            );
71
        } else if (params.tickUpper % params.tickSpacing != 0) {
72
            vm.expectRevert(
73
                abi.encodeWithSelector(TickBitmap.TickMisaligned.selector, params.tickUpper, params.tickSpacing)
74
            );
75
        } else {
76
            // We need the assumptions above to calculate this
77
            uint256 maxInt128InTypeU256 = uint256(uint128(Constants.MAX_UINT128));
78
            (uint256 amount0, uint256 amount1) = LiquidityAmounts.getAmountsForLiquidity(
79
                sqrtPriceX96,
80
                TickMath.getSqrtPriceAtTick(params.tickLower),
81
                TickMath.getSqrtPriceAtTick(params.tickUpper),
82
                uint128(params.liquidityDelta)
83
            );
84

                            
                        
85
            if ((amount0 > maxInt128InTypeU256) || (amount1 > maxInt128InTypeU256)) {
86
                vm.expectRevert(abi.encodeWithSelector(SafeCast.SafeCastOverflow.selector));
87
            }
88
        }
89

                            
                        
90
        params.owner = address(this);
91
        state.modifyLiquidity(params);
92
    }
93

                            
                        
94
    function test_fuzz_swap(
95
        uint160 sqrtPriceX96,
96
        uint24 lpFee,
97
        uint16 protocolFee0,
98
        uint16 protocolFee1,
99
        Pool.SwapParams memory params
100
    ) public {
101
        // Assumptions tested in PoolManager.t.sol
102
        params.tickSpacing = int24(bound(params.tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING));
103
        lpFee = uint24(bound(lpFee, 0, MAX_LP_FEE));
104
        protocolFee0 = uint16(bound(protocolFee0, 0, MAX_PROTOCOL_FEE));
105
        protocolFee1 = uint16(bound(protocolFee1, 0, MAX_PROTOCOL_FEE));
106
        uint24 protocolFee = protocolFee1 << 12 | protocolFee0;
107

                            
                        
108
        // initialize and add liquidity
109
        testModifyLiquidity(
110
            sqrtPriceX96,
111
            protocolFee,
112
            lpFee,
113
            Pool.ModifyLiquidityParams({
114
                owner: address(this),
115
                tickLower: -120,
116
                tickUpper: 120,
117
                liquidityDelta: 1e18,
118
                tickSpacing: 60,
119
                salt: 0
120
            })
121
        );
122
        Slot0 slot0 = state.slot0;
123

                            
                        
124
        uint24 _lpFee = params.lpFeeOverride.isOverride() ? params.lpFeeOverride.removeOverrideFlag() : lpFee;
125
        uint24 swapFee = protocolFee == 0 ? _lpFee : uint16(protocolFee).calculateSwapFee(_lpFee);
126

                            
                        
127
        if (params.amountSpecified >= 0 && swapFee == MAX_LP_FEE) {
128
            vm.expectRevert(Pool.InvalidFeeForExactOut.selector);
129
            state.swap(params);
130
        } else if (!_lpFee.isValid()) {
131
            vm.expectRevert(abi.encodeWithSelector(LPFeeLibrary.LPFeeTooLarge.selector, _lpFee));
132
            state.swap(params);
133
        } else if (params.zeroForOne && params.amountSpecified != 0) {
134
            if (params.sqrtPriceLimitX96 >= slot0.sqrtPriceX96()) {
135
                vm.expectRevert(
136
                    abi.encodeWithSelector(
137
                        Pool.PriceLimitAlreadyExceeded.selector, slot0.sqrtPriceX96(), params.sqrtPriceLimitX96
138
                    )
139
                );
140
                state.swap(params);
141
            } else if (params.sqrtPriceLimitX96 <= TickMath.MIN_SQRT_PRICE) {
142
                vm.expectRevert(abi.encodeWithSelector(Pool.PriceLimitOutOfBounds.selector, params.sqrtPriceLimitX96));
143
                state.swap(params);
144
            }
145
        } else if (!params.zeroForOne && params.amountSpecified != 0) {
146
            if (params.sqrtPriceLimitX96 <= slot0.sqrtPriceX96()) {
147
                vm.expectRevert(
148
                    abi.encodeWithSelector(
149
                        Pool.PriceLimitAlreadyExceeded.selector, slot0.sqrtPriceX96(), params.sqrtPriceLimitX96
150
                    )
151
                );
152
                state.swap(params);
153
            } else if (params.sqrtPriceLimitX96 >= TickMath.MAX_SQRT_PRICE) {
154
                vm.expectRevert(abi.encodeWithSelector(Pool.PriceLimitOutOfBounds.selector, params.sqrtPriceLimitX96));
155
                state.swap(params);
156
            }
157
        } else {
158
            uint160 sqrtPriceBefore = state.slot0.sqrtPriceX96();
159
            state.swap(params);
160

                            
                        
161
            if (params.amountSpecified == 0) {
162
                assertEq(sqrtPriceBefore, state.slot0.sqrtPriceX96(), "amountSpecified == 0");
163
            } else if (params.zeroForOne) {
164
                assertGe(state.slot0.sqrtPriceX96(), params.sqrtPriceLimitX96, "zeroForOne");
165
            } else {
166
                assertLe(state.slot0.sqrtPriceX96(), params.sqrtPriceLimitX96, "oneForZero");
167
            }
168
        }
169
    }
170

                            
                        
171
    function test_fuzz_tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) public pure {
172
        tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING));
173
        // v3 math
174
        int24 minTick = (TickMath.MIN_TICK / tickSpacing) * tickSpacing;
175
        int24 maxTick = (TickMath.MAX_TICK / tickSpacing) * tickSpacing;
176
        uint24 numTicks = uint24((maxTick - minTick) / tickSpacing) + 1;
177
        // assert that the result is the same as the v3 math
178
        assertEq(type(uint128).max / numTicks, Pool.tickSpacingToMaxLiquidityPerTick(tickSpacing));
179
    }
180
}
181

                            
                        

Lines covered: 0 / 4 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
6
import {PoolKey} from "../../src/types/PoolKey.sol";
7

                            
                        
8
contract PoolIdTest is Test {
9
    using PoolIdLibrary for PoolKey;
10

                            
                        
11
    function test_fuzz_toId(PoolKey memory poolKey) public pure {
12
        bytes memory encodedKey = abi.encode(poolKey);
13
        bytes32 expectedHash = keccak256(encodedKey);
14
        assertEq(PoolId.unwrap(poolKey.toId()), expectedHash, "hashes not equal");
15
    }
16
}
17

                            
                        

Lines covered: 0 / 35 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Position} from "../../src/libraries/Position.sol";
6
import {SafeCast} from "../../src/libraries/SafeCast.sol";
7

                            
                        
8
contract PositionTest is Test {
9
    using Position for mapping(bytes32 => Position.Info);
10

                            
                        
11
    mapping(bytes32 => Position.Info) internal positions;
12

                            
                        
13
    function test_fuzz_get(address owner, int24 tickLower, int24 tickUpper, bytes32 salt) public view {
14
        bytes32 positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt));
15
        Position.Info storage expectedPosition = positions[positionKey];
16
        Position.Info storage position = positions.get(owner, tickLower, tickUpper, salt);
17
        bytes32 expectedPositionSlot;
18
        bytes32 positionSlot;
19
        assembly ("memory-safe") {
20
            expectedPositionSlot := expectedPosition.slot
21
            positionSlot := position.slot
22
        }
23
        assertEq(positionSlot, expectedPositionSlot, "slots not equal");
24
    }
25

                            
                        
26
    function test_fuzz_update(
27
        int128 liquidityDelta,
28
        Position.Info memory pos,
29
        uint256 newFeeGrowthInside0X128,
30
        uint256 newFeeGrowthInside1X128
31
    ) public {
32
        Position.Info storage position = positions[0];
33
        position.liquidity = pos.liquidity;
34
        position.feeGrowthInside0LastX128 = pos.feeGrowthInside0LastX128;
35
        position.feeGrowthInside1LastX128 = pos.feeGrowthInside1LastX128;
36

                            
                        
37
        uint128 oldLiquidity = position.liquidity;
38

                            
                        
39
        if (position.liquidity == 0 && liquidityDelta == 0) {
40
            vm.expectRevert(Position.CannotUpdateEmptyPosition.selector);
41
        }
42

                            
                        
43
        // new liquidity cannot overflow/underflow uint128
44
        uint256 absLiquidityDelta;
45
        if (liquidityDelta > 0) {
46
            absLiquidityDelta = uint256(uint128(liquidityDelta));
47
            uint256 newLiquidity = position.liquidity + absLiquidityDelta;
48
            if (newLiquidity > type(uint128).max) {
49
                vm.expectRevert(SafeCast.SafeCastOverflow.selector);
50
            }
51
        } else if (liquidityDelta < 0) {
52
            if (liquidityDelta == type(int128).min) {
53
                absLiquidityDelta = uint256(uint128(type(int128).max)) + 1;
54
            } else {
55
                absLiquidityDelta = uint256(uint128(-liquidityDelta));
56
            }
57
            if (position.liquidity < absLiquidityDelta) {
58
                vm.expectRevert(SafeCast.SafeCastOverflow.selector);
59
            }
60
        }
61

                            
                        
62
        Position.update(position, liquidityDelta, newFeeGrowthInside0X128, newFeeGrowthInside1X128);
63
        if (liquidityDelta == 0) {
64
            assertEq(position.liquidity, oldLiquidity);
65
        } else if (liquidityDelta > 0) {
66
            assertEq(position.liquidity, oldLiquidity + absLiquidityDelta);
67
        } else {
68
            assertEq(position.liquidity, oldLiquidity - absLiquidityDelta);
69
        }
70

                            
                        
71
        assertEq(position.feeGrowthInside0LastX128, newFeeGrowthInside0X128);
72
        assertEq(position.feeGrowthInside1LastX128, newFeeGrowthInside1X128);
73
    }
74
}
75

                            
                        

Lines covered: 0 / 36 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
6
import {LPFeeLibrary} from "../../src/libraries/LPFeeLibrary.sol";
7
import {ProtocolFeeLibrary} from "../../src/libraries/ProtocolFeeLibrary.sol";
8

                            
                        
9
contract ProtocolFeeLibraryTest is Test, GasSnapshot {
10
    function test_getZeroForOneFee() public pure {
11
        uint24 fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE;
12
        assertEq(ProtocolFeeLibrary.getZeroForOneFee(fee), uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE));
13
    }
14

                            
                        
15
    function test_fuzz_getZeroForOneFee(uint24 fee) public pure {
16
        assertEq(ProtocolFeeLibrary.getZeroForOneFee(fee), fee % 4096);
17
    }
18

                            
                        
19
    function test_getOneForZeroFee() public pure {
20
        uint24 fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE;
21
        assertEq(ProtocolFeeLibrary.getOneForZeroFee(fee), uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1));
22
    }
23

                            
                        
24
    function test_fuzz_getOneForZeroFee(uint24 fee) public pure {
25
        assertEq(ProtocolFeeLibrary.getOneForZeroFee(fee), fee >> 12);
26
    }
27

                            
                        
28
    function test_isValidProtocolFee_fee() public pure {
29
        uint24 fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE + 1) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE;
30
        assertFalse(ProtocolFeeLibrary.isValidProtocolFee(fee));
31

                            
                        
32
        fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE) << 12 | (ProtocolFeeLibrary.MAX_PROTOCOL_FEE + 1);
33
        assertFalse(ProtocolFeeLibrary.isValidProtocolFee(fee));
34

                            
                        
35
        fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE + 1) << 12 | (ProtocolFeeLibrary.MAX_PROTOCOL_FEE + 1);
36
        assertFalse(ProtocolFeeLibrary.isValidProtocolFee(fee));
37

                            
                        
38
        fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE;
39
        assertTrue(ProtocolFeeLibrary.isValidProtocolFee(fee));
40

                            
                        
41
        fee = uint24(ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1) << 12 | ProtocolFeeLibrary.MAX_PROTOCOL_FEE - 1;
42
        assertTrue(ProtocolFeeLibrary.isValidProtocolFee(fee));
43

                            
                        
44
        fee = uint24(0) << 12 | uint24(0);
45
        assertTrue(ProtocolFeeLibrary.isValidProtocolFee(fee));
46
    }
47

                            
                        
48
    function test_fuzz_isValidProtocolFee(uint24 fee) public pure {
49
        if ((fee >> 12 > ProtocolFeeLibrary.MAX_PROTOCOL_FEE) || (fee % 4096 > ProtocolFeeLibrary.MAX_PROTOCOL_FEE)) {
50
            assertFalse(ProtocolFeeLibrary.isValidProtocolFee(fee));
51
        } else {
52
            assertTrue(ProtocolFeeLibrary.isValidProtocolFee(fee));
53
        }
54
    }
55

                            
                        
56
    function test_calculateSwapFee() public pure {
57
        assertEq(
58
            ProtocolFeeLibrary.calculateSwapFee(uint16(ProtocolFeeLibrary.MAX_PROTOCOL_FEE), LPFeeLibrary.MAX_LP_FEE),
59
            LPFeeLibrary.MAX_LP_FEE
60
        );
61
        assertEq(ProtocolFeeLibrary.calculateSwapFee(uint16(ProtocolFeeLibrary.MAX_PROTOCOL_FEE), 3000), 3997);
62
        assertEq(
63
            ProtocolFeeLibrary.calculateSwapFee(uint16(ProtocolFeeLibrary.MAX_PROTOCOL_FEE), 0),
64
            ProtocolFeeLibrary.MAX_PROTOCOL_FEE
65
        );
66
        assertEq(ProtocolFeeLibrary.calculateSwapFee(0, 0), 0);
67
        assertEq(ProtocolFeeLibrary.calculateSwapFee(0, 1000), 1000);
68
    }
69

                            
                        
70
    function test_fuzz_calculateSwapFee(uint16 protocolFee, uint24 lpFee) public pure {
71
        protocolFee = uint16(bound(protocolFee, 0, ProtocolFeeLibrary.MAX_PROTOCOL_FEE));
72
        lpFee = uint24(bound(lpFee, 0, LPFeeLibrary.MAX_LP_FEE));
73
        uint24 swapFee = ProtocolFeeLibrary.calculateSwapFee(protocolFee, lpFee);
74
        // if lp fee is not the max, the swap fee should never be the max since the protocol fee is taken off first and then the lp fee is taken from the remaining amount
75
        if (lpFee < LPFeeLibrary.MAX_LP_FEE) {
76
            assertLt(swapFee, LPFeeLibrary.MAX_LP_FEE);
77
        } else {
78
            // otherwise it is equal to max, and can therefore never be larger
79
            assertEq(swapFee, LPFeeLibrary.MAX_LP_FEE);
80
        }
81

                            
                        
82
        assertGe(swapFee, lpFee);
83

                            
                        
84
        uint256 expectedSwapFee =
85
            protocolFee + lpFee * uint256(LPFeeLibrary.MAX_LP_FEE - protocolFee) / LPFeeLibrary.MAX_LP_FEE;
86
        assertEq(swapFee, uint24(expectedSwapFee));
87
    }
88
}
89

                            
                        

Lines covered: 0 / 44 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Vm} from "forge-std/Vm.sol";
6
import {SafeCast} from "../../src/libraries/SafeCast.sol";
7

                            
                        
8
contract SafeCastTest is Test {
9
    function test_fuzz_toUint160(uint256 x) public {
10
        if (x <= type(uint160).max) {
11
            assertEq(uint256(SafeCast.toUint160(x)), x);
12
        } else {
13
            vm.expectRevert(SafeCast.SafeCastOverflow.selector);
14
            SafeCast.toUint160(x);
15
        }
16
    }
17

                            
                        
18
    function test_toUint160() public {
19
        assertEq(uint256(SafeCast.toUint160(0)), 0);
20
        assertEq(uint256(SafeCast.toUint160(type(uint160).max)), type(uint160).max);
21
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
22
        SafeCast.toUint160(type(uint160).max + uint256(1));
23
    }
24

                            
                        
25
    function test_fuzz_toUint128(uint256 x) public {
26
        if (x <= type(uint128).max) {
27
            assertEq(uint256(SafeCast.toUint128(x)), x);
28
        } else {
29
            vm.expectRevert(SafeCast.SafeCastOverflow.selector);
30
            SafeCast.toUint128(x);
31
        }
32
    }
33

                            
                        
34
    function test_toUint128() public {
35
        assertEq(uint256(SafeCast.toUint128(0)), 0);
36
        assertEq(uint256(SafeCast.toUint128(type(uint128).max)), type(uint128).max);
37
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
38
        SafeCast.toUint128(type(uint128).max + uint256(1));
39
    }
40

                            
                        
41
    function test_fuzz_toInt128_fromInt256(int256 x) public {
42
        if (x <= type(int128).max && x >= type(int128).min) {
43
            assertEq(int256(SafeCast.toInt128(x)), x);
44
        } else {
45
            vm.expectRevert(SafeCast.SafeCastOverflow.selector);
46
            SafeCast.toInt128(x);
47
        }
48
    }
49

                            
                        
50
    function test_toInt128_fromInt256() public {
51
        assertEq(int256(SafeCast.toInt128(int256(0))), 0);
52
        assertEq(int256(SafeCast.toInt128(type(int128).max)), type(int128).max);
53
        assertEq(int256(SafeCast.toInt128(type(int128).min)), type(int128).min);
54
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
55
        SafeCast.toInt128(type(int128).max + int256(1));
56
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
57
        SafeCast.toInt128(type(int128).min - int256(1));
58
    }
59

                            
                        
60
    function test_fuzz_toInt256(uint256 x) public {
61
        if (x <= uint256(type(int256).max)) {
62
            assertEq(uint256(SafeCast.toInt256(x)), x);
63
        } else {
64
            vm.expectRevert(SafeCast.SafeCastOverflow.selector);
65
            SafeCast.toInt256(x);
66
        }
67
    }
68

                            
                        
69
    function test_toInt256() public {
70
        assertEq(uint256(SafeCast.toInt256(0)), 0);
71
        assertEq(uint256(SafeCast.toInt256(uint256(type(int256).max))), uint256(type(int256).max));
72
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
73
        SafeCast.toInt256(uint256(type(int256).max) + uint256(1));
74
    }
75

                            
                        
76
    function test_fuzz_toInt128_fromUint256(uint256 x) public {
77
        if (x <= uint128(type(int128).max)) {
78
            assertEq(uint128(SafeCast.toInt128(x)), x);
79
        } else {
80
            vm.expectRevert(SafeCast.SafeCastOverflow.selector);
81
            SafeCast.toInt128(x);
82
        }
83
    }
84

                            
                        
85
    function test_toInt128_fromUint256() public {
86
        assertEq(uint128(SafeCast.toInt128(uint256(0))), 0);
87
        assertEq(uint128(SafeCast.toInt128(uint256(uint128(type(int128).max)))), uint128(type(int128).max));
88
        vm.expectRevert(SafeCast.SafeCastOverflow.selector);
89
        SafeCast.toInt128(uint256(uint128(type(int128).max)) + uint256(1));
90
    }
91
}
92

                            
                        

Lines covered: 0 / 132 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Vm} from "forge-std/Vm.sol";
6
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
7
import {SqrtPriceMath} from "../../src/libraries/SqrtPriceMath.sol";
8
import {Constants} from "../../test/utils/Constants.sol";
9

                            
                        
10
contract SqrtPriceMathTest is Test, GasSnapshot {
11
    function test_getNextSqrtPriceFromInput_revertsIfPriceIsZero() public {
12
        vm.expectRevert(SqrtPriceMath.InvalidPriceOrLiquidity.selector);
13
        SqrtPriceMath.getNextSqrtPriceFromInput(0, 1, 0.1 ether, false);
14
    }
15

                            
                        
16
    function test_getNextSqrtPriceFromInput_revertsIfLiquidityIsZero() public {
17
        vm.expectRevert(SqrtPriceMath.InvalidPriceOrLiquidity.selector);
18
        SqrtPriceMath.getNextSqrtPriceFromInput(1, 0, 0.1 ether, true);
19
    }
20

                            
                        
21
    function test_getNextSqrtPriceFromInput_revertsIfInputAmountOverflowsThePrice() public {
22
        uint160 price = Constants.MAX_UINT160 - 1;
23
        uint128 liquidity = 1024;
24
        uint256 amountIn = 1024;
25

                            
                        
26
        vm.expectRevert();
27
        SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, amountIn, false);
28
    }
29

                            
                        
30
    function test_getNextSqrtPriceFromInput_anyInputAmountCannotUnderflowThePrice() public pure {
31
        uint160 price = 1;
32
        uint128 liquidity = 1;
33
        uint256 amountIn = 2 ** 255;
34

                            
                        
35
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, amountIn, true);
36

                            
                        
37
        assertEq(sqrtQ, 1);
38
    }
39

                            
                        
40
    function test_getNextSqrtPriceFromInput_returnsInputPriceIfAmountInIsZeroAndZeroForOneEqualsTrue() public pure {
41
        uint160 price = Constants.SQRT_PRICE_1_1;
42
        uint128 liquidity = 1;
43

                            
                        
44
        assertEq(SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, 0, true), price);
45
    }
46

                            
                        
47
    function test_getNextSqrtPriceFromInput_returnsInputPriceIfAmountInIsZeroAndZeroForOneEqualsFalse() public pure {
48
        uint160 price = Constants.SQRT_PRICE_1_1;
49
        uint128 liquidity = 1;
50

                            
                        
51
        assertEq(SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, 0, false), price);
52
    }
53

                            
                        
54
    function test_getNextSqrtPriceFromInput_returnsTheMinimumPriceForMaxInputs() public pure {
55
        uint160 sqrtP = Constants.MAX_UINT160 - 1;
56
        uint128 liquidity = Constants.MAX_UINT128;
57
        uint256 maxAmountNoOverflow = Constants.MAX_UINT256 - Constants.MAX_UINT128 << 96 / sqrtP;
58

                            
                        
59
        assertEq(SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, liquidity, maxAmountNoOverflow, true), 1);
60
    }
61

                            
                        
62
    function test_getNextSqrtPriceFromInput_inputAmountOf0_1Currency1() public pure {
63
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
64

                            
                        
65
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(1 ether), 0.1 ether, false);
66

                            
                        
67
        assertEq(sqrtQ, Constants.SQRT_PRICE_121_100);
68
    }
69

                            
                        
70
    function test_getNextSqrtPriceFromInput_inputAmountOf0_1Currency0() public pure {
71
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
72

                            
                        
73
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(1 ether), 0.1 ether, true);
74

                            
                        
75
        assertEq(sqrtQ, 72025602285694852357767227579);
76
    }
77

                            
                        
78
    function test_getNextSqrtPriceFromInput_amountInGreaterThanType_uint96_maxAndZeroForOneEqualsTrue() public pure {
79
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
80

                            
                        
81
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(10 ether), 2 ** 100, true);
82

                            
                        
83
        // perfect answer:
84
        // https://www.wolframalpha.com/input/?i=624999999995069620+-+%28%281e19+*+1+%2F+%281e19+%2B+2%5E100+*+1%29%29+*+2%5E96%29
85
        assertEq(sqrtQ, 624999999995069620);
86
    }
87

                            
                        
88
    function test_getNextSqrtPriceFromInput_canReturn1WithEnoughAmountInAndZeroForOneEqualsTrue() public pure {
89
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
90

                            
                        
91
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, 1, Constants.MAX_UINT256 / 2, true);
92

                            
                        
93
        assertEq(sqrtQ, 1);
94
    }
95

                            
                        
96
    //
97
    function test_getNextSqrtPriceFromInput_zeroForOneEqualsTrueGas() public {
98
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
99

                            
                        
100
        snapStart("getNextSqrtPriceFromInput_zeroForOneEqualsTrueGas");
101
        SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(1 ether), 0.1 ether, true);
102
        snapEnd();
103
    }
104

                            
                        
105
    function test_getNextSqrtPriceFromInput_zeroForOneEqualsFalseGas() public {
106
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
107

                            
                        
108
        snapStart("getNextSqrtPriceFromInput_zeroForOneEqualsFalseGas");
109
        SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, uint128(1 ether), 0.1 ether, false);
110
        snapEnd();
111
    }
112

                            
                        
113
    function test_getNextSqrtPriceFromOutput_revertsIfPriceIsZero() public {
114
        vm.expectRevert(SqrtPriceMath.InvalidPriceOrLiquidity.selector);
115
        SqrtPriceMath.getNextSqrtPriceFromOutput(0, 1, 0.1 ether, false);
116
    }
117

                            
                        
118
    function test_getNextSqrtPriceFromOutput_revertsIfLiquidityIsZero() public {
119
        vm.expectRevert(SqrtPriceMath.InvalidPriceOrLiquidity.selector);
120
        SqrtPriceMath.getNextSqrtPriceFromOutput(1, 0, 0.1 ether, true);
121
    }
122

                            
                        
123
    function test_getNextSqrtPriceFromOutput_revertsIfOutputAmountIsExactlyTheVirtualReservesOfCurrency0() public {
124
        uint160 price = 20282409603651670423947251286016;
125
        uint128 liquidity = 1024;
126
        uint256 amountOut = 4;
127

                            
                        
128
        vm.expectRevert(SqrtPriceMath.PriceOverflow.selector);
129
        SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, false);
130
    }
131

                            
                        
132
    function test_getNextSqrtPriceFromOutput_revertsIfOutputAmountIsGreaterThanTheVirtualReservesOfCurrency0() public {
133
        uint160 price = 20282409603651670423947251286016;
134
        uint128 liquidity = 1024;
135
        uint256 amountOut = 5;
136

                            
                        
137
        vm.expectRevert(SqrtPriceMath.PriceOverflow.selector);
138
        SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, false);
139
    }
140

                            
                        
141
    function test_getNextSqrtPriceFromOutput_revertsIfOutputAmountIsGreaterThanTheVirtualReservesOfCurrency1() public {
142
        uint160 price = 20282409603651670423947251286016;
143
        uint128 liquidity = 1024;
144
        uint256 amountOut = 262145;
145

                            
                        
146
        vm.expectRevert(SqrtPriceMath.NotEnoughLiquidity.selector);
147
        SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, true);
148
    }
149

                            
                        
150
    function test_getNextSqrtPriceFromOutput_revertsIfOutputAmountIsExactlyTheVirtualReservesOfCurrency1() public {
151
        uint160 price = 20282409603651670423947251286016;
152
        uint128 liquidity = 1024;
153
        uint256 amountOut = 262144;
154

                            
                        
155
        vm.expectRevert(SqrtPriceMath.NotEnoughLiquidity.selector);
156
        SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, true);
157
    }
158

                            
                        
159
    function test_getNextSqrtPriceFromOutput_succeedsIfOutputAmountIsJustLessThanTheVirtualReservesOfCurrency1()
160
        public
161
        pure
162
    {
163
        uint160 price = 20282409603651670423947251286016;
164
        uint128 liquidity = 1024;
165
        uint256 amountOut = 262143;
166

                            
                        
167
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, true);
168

                            
                        
169
        assertEq(sqrtQ, 77371252455336267181195264);
170
    }
171

                            
                        
172
    function test_getNextSqrtPriceFromOutput_puzzlingEchidnaTest() public {
173
        uint160 price = 20282409603651670423947251286016;
174
        uint128 liquidity = 1024;
175
        uint256 amountOut = 4;
176

                            
                        
177
        vm.expectRevert(SqrtPriceMath.PriceOverflow.selector);
178
        SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, amountOut, false);
179
    }
180

                            
                        
181
    function test_getNextSqrtPriceFromOutput_returnsInputPriceIfAmountInIsZeroAndZeroForOneEqualsTrue() public pure {
182
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
183

                            
                        
184
        uint256 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(0.1 ether), 0, true);
185

                            
                        
186
        assertEq(sqrtP, sqrtQ);
187
    }
188

                            
                        
189
    function test_getNextSqrtPriceFromOutput_returnsInputPriceIfAmountInIsZeroAndZeroForOneEqualsFalse() public pure {
190
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
191

                            
                        
192
        uint256 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(0.1 ether), 0, false);
193

                            
                        
194
        assertEq(sqrtP, sqrtQ);
195
    }
196

                            
                        
197
    function test_getNextSqrtPriceFromOutput_outputAmountOf0_1Currency1() public pure {
198
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
199

                            
                        
200
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(1 ether), 0.1 ether, false);
201

                            
                        
202
        assertEq(sqrtQ, 88031291682515930659493278152);
203
    }
204

                            
                        
205
    function test_getNextSqrtPriceFromOutput_outputAmountOf0_1Currency0() public pure {
206
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
207

                            
                        
208
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(1 ether), 0.1 ether, true);
209

                            
                        
210
        assertEq(sqrtQ, 71305346262837903834189555302);
211
    }
212

                            
                        
213
    function test_getNextSqrtPriceFromOutput_revertsIfAmountOutIsImpossibleInZeroForOneDirection() public {
214
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
215

                            
                        
216
        vm.expectRevert();
217
        SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, 1, Constants.MAX_UINT256, true);
218
    }
219

                            
                        
220
    function test_getNextSqrtPriceFromOutput_revertsIfAmountOutIsImpossibleInOneForZeroDirection() public {
221
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
222

                            
                        
223
        vm.expectRevert(SqrtPriceMath.PriceOverflow.selector);
224
        SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, 1, Constants.MAX_UINT256, false);
225
    }
226

                            
                        
227
    function test_getNextSqrtPriceFromOutput_zeroForOneEqualsTrueGas() public {
228
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
229

                            
                        
230
        snapStart("getNextSqrtPriceFromOutput_zeroForOneEqualsTrueGas");
231
        SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(1 ether), 0.1 ether, true);
232
        snapEnd();
233
    }
234

                            
                        
235
    function test_getNextSqrtPriceFromOutput_zeroForOneEqualsFalseGas() public {
236
        uint160 sqrtP = Constants.SQRT_PRICE_1_1;
237

                            
                        
238
        snapStart("getNextSqrtPriceFromOutput_zeroForOneEqualsFalseGas");
239
        SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtP, uint128(1 ether), 0.1 ether, false);
240
        snapEnd();
241
    }
242

                            
                        
243
    function test_getAmount0Delta_returns0IfLiquidityIs0() public pure {
244
        uint256 amount0 = SqrtPriceMath.getAmount0Delta(Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_2_1, 0, true);
245

                            
                        
246
        assertEq(amount0, 0);
247
    }
248

                            
                        
249
    function test_getAmount0Delta_returns0IfPricesAreEqual() public pure {
250
        uint256 amount0 = SqrtPriceMath.getAmount0Delta(Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_1_1, 0, true);
251

                            
                        
252
        assertEq(amount0, 0);
253
    }
254

                            
                        
255
    function test_getAmount0Delta_revertsIfPriceIsZero() public {
256
        vm.expectRevert(SqrtPriceMath.InvalidPrice.selector);
257
        SqrtPriceMath.getAmount0Delta(0, 1, 1, true);
258
    }
259

                            
                        
260
    function test_getAmount0Delta_1Amount1ForPriceOf1To1_21() public pure {
261
        uint256 amount0 = SqrtPriceMath.getAmount0Delta(
262
            Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_121_100, uint128(1 ether), true
263
        );
264

                            
                        
265
        assertEq(amount0, 90909090909090910);
266

                            
                        
267
        uint256 amount0RoundedDown = SqrtPriceMath.getAmount0Delta(
268
            Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_121_100, uint128(1 ether), false
269
        );
270

                            
                        
271
        assertEq(amount0RoundedDown, amount0 - 1);
272
    }
273

                            
                        
274
    function test_getAmount0Delta_worksForPricesThatOverflow() public pure {
275
        // sqrtP_1 = encodeSqrtPriceX96(2^90, 1)
276
        uint160 sqrtP_1 = 2787593149816327892691964784081045188247552;
277
        // sqrtP_2 = encodeSqrtPriceX96(2^96, 1)
278
        uint160 sqrtP_2 = 22300745198530623141535718272648361505980416;
279

                            
                        
280
        uint256 amount0Up = SqrtPriceMath.getAmount0Delta(sqrtP_1, sqrtP_2, uint128(1 ether), true);
281

                            
                        
282
        uint256 amount0Down = SqrtPriceMath.getAmount0Delta(sqrtP_1, sqrtP_2, uint128(1 ether), false);
283

                            
                        
284
        assertEq(amount0Up, amount0Down + 1);
285
    }
286

                            
                        
287
    function test_getAmount0Delta_gasCostForAmount0WhereRoundUpIsTrue() public {
288
        snapStart("getAmount0Delta_gasCostForAmount0WhereRoundUpIsTrue");
289
        SqrtPriceMath.getAmount0Delta(Constants.SQRT_PRICE_121_100, Constants.SQRT_PRICE_1_1, uint128(1 ether), true);
290
        snapEnd();
291
    }
292

                            
                        
293
    function test_getAmount0Delta_gasCostForAmount0WhereRoundUpIsFalse() public {
294
        snapStart("getAmount0Delta_gasCostForAmount0WhereRoundUpIsFalse");
295
        SqrtPriceMath.getAmount0Delta(Constants.SQRT_PRICE_121_100, Constants.SQRT_PRICE_1_1, uint128(1 ether), false);
296
        snapEnd();
297
    }
298

                            
                        
299
    function test_getAmount1Delta_returns0IfLiquidityIs0() public pure {
300
        uint256 amount1 = SqrtPriceMath.getAmount1Delta(Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_2_1, 0, true);
301

                            
                        
302
        assertEq(amount1, 0);
303
    }
304

                            
                        
305
    function test_getAmount1Delta_returns0IfPricesAreEqual() public pure {
306
        uint256 amount1 = SqrtPriceMath.getAmount1Delta(Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_1_1, 0, true);
307

                            
                        
308
        assertEq(amount1, 0);
309
    }
310

                            
                        
311
    function test_getAmount1Delta_1Amount1ForPriceOf1To1_21() public pure {
312
        uint256 amount1 = SqrtPriceMath.getAmount1Delta(
313
            Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_121_100, uint128(1 ether), true
314
        );
315

                            
                        
316
        assertEq(amount1, 100000000000000000);
317

                            
                        
318
        uint256 amount1RoundedDown = SqrtPriceMath.getAmount1Delta(
319
            Constants.SQRT_PRICE_1_1, Constants.SQRT_PRICE_121_100, uint128(1 ether), false
320
        );
321

                            
                        
322
        assertEq(amount1RoundedDown, amount1 - 1);
323
    }
324

                            
                        
325
    function test_getAmount1Delta_gasCostForAmount1WhereRoundUpIsTrue() public {
326
        snapStart("getAmount1Delta_gasCostForAmount1WhereRoundUpIsTrue");
327
        SqrtPriceMath.getAmount1Delta(Constants.SQRT_PRICE_121_100, Constants.SQRT_PRICE_1_1, uint128(1 ether), true);
328
        snapEnd();
329
    }
330

                            
                        
331
    function test_getAmount1Delta_gasCostForAmount1WhereRoundUpIsFalse() public {
332
        snapStart("getAmount1Delta_gasCostForAmount1WhereRoundUpIsFalse");
333
        SqrtPriceMath.getAmount1Delta(Constants.SQRT_PRICE_121_100, Constants.SQRT_PRICE_1_1, uint128(1 ether), false);
334
        snapEnd();
335
    }
336

                            
                        
337
    function test_swapComputation_sqrtPTimessqrtQOverflows() public pure {
338
        // getNextSqrtPriceInvariants(1025574284609383690408304870162715216695788925244,50015962439936049619261659728067971248,406,true)
339
        uint160 sqrtP = 1025574284609383690408304870162715216695788925244;
340
        uint128 liquidity = 50015962439936049619261659728067971248;
341
        bool zeroForOne = true;
342
        uint128 amountIn = 406;
343

                            
                        
344
        uint160 sqrtQ = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, liquidity, amountIn, zeroForOne);
345
        assertEq(sqrtQ, 1025574284609383582644711336373707553698163132913);
346

                            
                        
347
        uint256 amount0Delta = SqrtPriceMath.getAmount0Delta(sqrtQ, sqrtP, liquidity, true);
348
        assertEq(amount0Delta, 406);
349
    }
350
}
351

                            
                        

Lines covered: 0 / 273 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.19;
3

                            
                        
4
import "forge-std/Test.sol";
5
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
6
import {IHooks} from "../../src/interfaces/IHooks.sol";
7
import {Hooks} from "../../src/libraries/Hooks.sol";
8
import {TickMath} from "../../src/libraries/TickMath.sol";
9
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
10
import {PoolKey} from "../../src/types/PoolKey.sol";
11
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
12
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
13
import {CurrencyLibrary, Currency} from "../../src/types/Currency.sol";
14
import {Deployers} from "../utils/Deployers.sol";
15
import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";
16
import {Pool} from "../../src/libraries/Pool.sol";
17
import {TickBitmap} from "../../src/libraries/TickBitmap.sol";
18
import {FixedPoint128} from "../../src/libraries/FixedPoint128.sol";
19

                            
                        
20
import {StateLibrary} from "../../src/libraries/StateLibrary.sol";
21
import {Fuzzers} from "../../src/test/Fuzzers.sol";
22

                            
                        
23
contract StateLibraryTest is Test, Deployers, Fuzzers, GasSnapshot {
24
    using FixedPointMathLib for uint256;
25
    using PoolIdLibrary for PoolKey;
26

                            
                        
27
    PoolId poolId;
28

                            
                        
29
    function setUp() public {
30
        // creates the pool manager, utility routers, and test tokens
31
        Deployers.deployFreshManagerAndRouters();
32
        (currency0, currency1) = Deployers.deployMintAndApprove2Currencies();
33

                            
                        
34
        // Create the pool
35
        key = PoolKey(currency0, currency1, 3000, 60, IHooks(address(0x0)));
36
        poolId = key.toId();
37
        manager.initialize(key, SQRT_PRICE_1_1, ZERO_BYTES);
38
    }
39

                            
                        
40
    function test_getSlot0() public {
41
        // create liquidity
42
        modifyLiquidityRouter.modifyLiquidity(
43
            key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES
44
        );
45

                            
                        
46
        modifyLiquidityRouter.modifyLiquidity(
47
            key, IPoolManager.ModifyLiquidityParams(-600, 600, 10_000 ether, 0), ZERO_BYTES
48
        );
49

                            
                        
50
        // swap to create fees, crossing a tick
51
        uint256 swapAmount = 100 ether;
52
        swap(key, true, -int256(swapAmount), ZERO_BYTES);
53
        (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 swapFee) = StateLibrary.getSlot0(manager, poolId);
54
        snapLastCall("extsload getSlot0");
55
        assertEq(tick, -139);
56

                            
                        
57
        // magic number verified against a native getter
58
        assertEq(sqrtPriceX96, 78680104762184586858280382455);
59
        assertEq(tick, -139);
60
        assertEq(protocolFee, 0); // tested in protocol fee tests
61
        assertEq(swapFee, 3000);
62
    }
63

                            
                        
64
    function test_getTickLiquidity() public {
65
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 10 ether, 0), ZERO_BYTES);
66

                            
                        
67
        (uint128 liquidityGrossLower, int128 liquidityNetLower) = StateLibrary.getTickLiquidity(manager, poolId, -60);
68
        snapLastCall("extsload getTickLiquidity");
69
        assertEq(liquidityGrossLower, 10 ether);
70
        assertEq(liquidityNetLower, 10 ether);
71

                            
                        
72
        (uint128 liquidityGrossUpper, int128 liquidityNetUpper) = StateLibrary.getTickLiquidity(manager, poolId, 60);
73
        assertEq(liquidityGrossUpper, 10 ether);
74
        assertEq(liquidityNetUpper, -10 ether);
75
    }
76

                            
                        
77
    function test_fuzz_getTickLiquidity(IPoolManager.ModifyLiquidityParams memory params) public {
78
        (IPoolManager.ModifyLiquidityParams memory _params,) =
79
            Fuzzers.createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES);
80
        uint128 liquidityDelta = uint128(uint256(_params.liquidityDelta));
81

                            
                        
82
        (uint128 liquidityGrossLower, int128 liquidityNetLower) =
83
            StateLibrary.getTickLiquidity(manager, poolId, _params.tickLower);
84
        assertEq(liquidityGrossLower, liquidityDelta);
85
        assertEq(liquidityNetLower, int128(_params.liquidityDelta));
86

                            
                        
87
        (uint128 liquidityGrossUpper, int128 liquidityNetUpper) =
88
            StateLibrary.getTickLiquidity(manager, poolId, _params.tickUpper);
89
        assertEq(liquidityGrossUpper, liquidityDelta);
90
        assertEq(liquidityNetUpper, -int128(_params.liquidityDelta));
91

                            
                        
92
        // confirm agreement with getTickInfo()
93
        (uint128 _liquidityGrossLower, int128 _liquidityNetLower,,) =
94
            StateLibrary.getTickInfo(manager, poolId, _params.tickLower);
95
        assertEq(_liquidityGrossLower, liquidityGrossLower);
96
        assertEq(_liquidityNetLower, liquidityNetLower);
97

                            
                        
98
        (uint128 _liquidityGrossUpper, int128 _liquidityNetUpper,,) =
99
            StateLibrary.getTickInfo(manager, poolId, _params.tickUpper);
100
        assertEq(_liquidityGrossUpper, liquidityGrossUpper);
101
        assertEq(_liquidityNetUpper, liquidityNetUpper);
102
    }
103

                            
                        
104
    function test_fuzz_getTickLiquidity_two_positions(
105
        IPoolManager.ModifyLiquidityParams memory paramsA,
106
        IPoolManager.ModifyLiquidityParams memory paramsB
107
    ) public {
108
        (IPoolManager.ModifyLiquidityParams memory _paramsA,) = Fuzzers.createFuzzyLiquidityWithTightBound(
109
            modifyLiquidityRouter, key, paramsA, SQRT_PRICE_1_1, ZERO_BYTES, 2
110
        );
111
        (IPoolManager.ModifyLiquidityParams memory _paramsB,) = Fuzzers.createFuzzyLiquidityWithTightBound(
112
            modifyLiquidityRouter, key, paramsB, SQRT_PRICE_1_1, ZERO_BYTES, 2
113
        );
114

                            
                        
115
        uint128 liquidityDeltaA = uint128(uint256(_paramsA.liquidityDelta));
116
        uint128 liquidityDeltaB = uint128(uint256(_paramsB.liquidityDelta));
117

                            
                        
118
        (uint128 liquidityGrossLowerA, int128 liquidityNetLowerA) =
119
            StateLibrary.getTickLiquidity(manager, poolId, _paramsA.tickLower);
120
        (uint128 liquidityGrossLowerB, int128 liquidityNetLowerB) =
121
            StateLibrary.getTickLiquidity(manager, poolId, _paramsB.tickLower);
122
        (uint256 liquidityGrossUpperA, int256 liquidityNetUpperA) =
123
            StateLibrary.getTickLiquidity(manager, poolId, _paramsA.tickUpper);
124
        (uint256 liquidityGrossUpperB, int256 liquidityNetUpperB) =
125
            StateLibrary.getTickLiquidity(manager, poolId, _paramsB.tickUpper);
126

                            
                        
127
        // when tick lower is shared between two positions, the gross liquidity is the sum
128
        if (_paramsA.tickLower == _paramsB.tickLower || _paramsA.tickLower == _paramsB.tickUpper) {
129
            assertEq(liquidityGrossLowerA, liquidityDeltaA + liquidityDeltaB);
130

                            
                        
131
            // when tick lower is shared with an upper tick, the net liquidity is the difference
132
            (_paramsA.tickLower == _paramsB.tickLower)
133
                ? assertEq(liquidityNetLowerA, int128(liquidityDeltaA + liquidityDeltaB))
134
                : assertApproxEqAbs(liquidityNetLowerA, int128(liquidityDeltaA) - int128(liquidityDeltaB), 1 wei);
135
        } else {
136
            assertEq(liquidityGrossLowerA, liquidityDeltaA);
137
            assertEq(liquidityNetLowerA, int128(liquidityDeltaA));
138
        }
139

                            
                        
140
        if (_paramsA.tickUpper == _paramsB.tickLower || _paramsA.tickUpper == _paramsB.tickUpper) {
141
            assertEq(liquidityGrossUpperA, liquidityDeltaA + liquidityDeltaB);
142
            (_paramsA.tickUpper == _paramsB.tickUpper)
143
                ? assertEq(liquidityNetUpperA, -int128(liquidityDeltaA + liquidityDeltaB))
144
                : assertApproxEqAbs(liquidityNetUpperA, int128(liquidityDeltaB) - int128(liquidityDeltaA), 2 wei);
145
        } else {
146
            assertEq(liquidityGrossUpperA, liquidityDeltaA);
147
            assertEq(liquidityNetUpperA, -int128(liquidityDeltaA));
148
        }
149

                            
                        
150
        if (_paramsB.tickLower == _paramsA.tickLower || _paramsB.tickLower == _paramsA.tickUpper) {
151
            assertEq(liquidityGrossLowerB, liquidityDeltaA + liquidityDeltaB);
152
            (_paramsB.tickLower == _paramsA.tickLower)
153
                ? assertEq(liquidityNetLowerB, int128(liquidityDeltaA + liquidityDeltaB))
154
                : assertApproxEqAbs(liquidityNetLowerB, int128(liquidityDeltaB) - int128(liquidityDeltaA), 1 wei);
155
        } else {
156
            assertEq(liquidityGrossLowerB, liquidityDeltaB);
157
            assertEq(liquidityNetLowerB, int128(liquidityDeltaB));
158
        }
159

                            
                        
160
        if (_paramsB.tickUpper == _paramsA.tickLower || _paramsB.tickUpper == _paramsA.tickUpper) {
161
            assertEq(liquidityGrossUpperB, liquidityDeltaA + liquidityDeltaB);
162
            (_paramsB.tickUpper == _paramsA.tickUpper)
163
                ? assertEq(liquidityNetUpperB, -int128(liquidityDeltaA + liquidityDeltaB))
164
                : assertApproxEqAbs(liquidityNetUpperB, int128(liquidityDeltaA) - int128(liquidityDeltaB), 2 wei);
165
        } else {
166
            assertEq(liquidityGrossUpperB, liquidityDeltaB);
167
            assertEq(liquidityNetUpperB, -int128(liquidityDeltaB));
168
        }
169
    }
170

                            
                        
171
    function test_getFeeGrowthGlobals0() public {
172
        // create liquidity
173
        uint256 liquidity = 10_000 ether;
174
        modifyLiquidityRouter.modifyLiquidity(
175
            key, IPoolManager.ModifyLiquidityParams(-60, 60, int256(liquidity), 0), ZERO_BYTES
176
        );
177

                            
                        
178
        (uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1) = StateLibrary.getFeeGrowthGlobals(manager, poolId);
179
        assertEq(feeGrowthGlobal0, 0);
180
        assertEq(feeGrowthGlobal1, 0);
181

                            
                        
182
        // swap to create fees on the input token (currency0)
183
        uint256 swapAmount = 10 ether;
184
        swap(key, true, -int256(swapAmount), ZERO_BYTES);
185

                            
                        
186
        (feeGrowthGlobal0, feeGrowthGlobal1) = StateLibrary.getFeeGrowthGlobals(manager, poolId);
187
        snapLastCall("extsload getFeeGrowthGlobals");
188

                            
                        
189
        uint256 feeGrowthGlobalCalc = swapAmount.mulWadDown(0.003e18).mulDivDown(FixedPoint128.Q128, liquidity);
190
        assertEq(feeGrowthGlobal0, feeGrowthGlobalCalc);
191
        assertEq(feeGrowthGlobal1, 0);
192
    }
193

                            
                        
194
    function test_getFeeGrowthGlobals1() public {
195
        // create liquidity
196
        uint256 liquidity = 10_000 ether;
197
        modifyLiquidityRouter.modifyLiquidity(
198
            key, IPoolManager.ModifyLiquidityParams(-60, 60, int256(liquidity), 0), ZERO_BYTES
199
        );
200

                            
                        
201
        (uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1) = StateLibrary.getFeeGrowthGlobals(manager, poolId);
202
        assertEq(feeGrowthGlobal0, 0);
203
        assertEq(feeGrowthGlobal1, 0);
204

                            
                        
205
        // swap to create fees on the input token (currency1)
206
        uint256 swapAmount = 10 ether;
207
        swap(key, false, -int256(swapAmount), ZERO_BYTES);
208

                            
                        
209
        (feeGrowthGlobal0, feeGrowthGlobal1) = StateLibrary.getFeeGrowthGlobals(manager, poolId);
210

                            
                        
211
        assertEq(feeGrowthGlobal0, 0);
212
        uint256 feeGrowthGlobalCalc = swapAmount.mulWadDown(0.003e18).mulDivDown(FixedPoint128.Q128, liquidity);
213
        assertEq(feeGrowthGlobal1, feeGrowthGlobalCalc);
214
    }
215

                            
                        
216
    function test_getLiquidity() public {
217
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 10 ether, 0), ZERO_BYTES);
218
        modifyLiquidityRouter.modifyLiquidity(
219
            key, IPoolManager.ModifyLiquidityParams(-120, 120, 10 ether, 0), ZERO_BYTES
220
        );
221

                            
                        
222
        uint128 liquidity = StateLibrary.getLiquidity(manager, poolId);
223
        snapLastCall("extsload getLiquidity");
224
        assertEq(liquidity, 20 ether);
225
    }
226

                            
                        
227
    function test_fuzz_getLiquidity(IPoolManager.ModifyLiquidityParams memory params) public {
228
        (IPoolManager.ModifyLiquidityParams memory _params,) =
229
            Fuzzers.createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES);
230
        (, int24 tick,,) = StateLibrary.getSlot0(manager, poolId);
231
        uint128 liquidity = StateLibrary.getLiquidity(manager, poolId);
232

                            
                        
233
        // out of range liquidity is not added to Pool.State.liquidity
234
        if (tick < _params.tickLower || tick >= _params.tickUpper) {
235
            assertEq(liquidity, 0);
236
        } else {
237
            assertEq(liquidity, uint128(uint256(_params.liquidityDelta)));
238
        }
239
    }
240

                            
                        
241
    function test_getTickBitmap() public {
242
        int24 tickLower = -300;
243
        int24 tickUpper = 300;
244
        // create liquidity
245
        modifyLiquidityRouter.modifyLiquidity(
246
            key, IPoolManager.ModifyLiquidityParams(tickLower, tickUpper, 10_000 ether, 0), ZERO_BYTES
247
        );
248

                            
                        
249
        (int16 wordPos, uint8 bitPos) = TickBitmap.position(tickLower / key.tickSpacing);
250
        uint256 tickBitmap = StateLibrary.getTickBitmap(manager, poolId, wordPos);
251
        snapLastCall("extsload getTickBitmap");
252
        assertNotEq(tickBitmap, 0);
253
        assertEq(tickBitmap, 1 << bitPos);
254

                            
                        
255
        (wordPos, bitPos) = TickBitmap.position(tickUpper / key.tickSpacing);
256
        tickBitmap = StateLibrary.getTickBitmap(manager, poolId, wordPos);
257
        assertNotEq(tickBitmap, 0);
258
        assertEq(tickBitmap, 1 << bitPos);
259
    }
260

                            
                        
261
    function test_fuzz_getTickBitmap(IPoolManager.ModifyLiquidityParams memory params) public {
262
        (IPoolManager.ModifyLiquidityParams memory _params,) =
263
            Fuzzers.createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES);
264

                            
                        
265
        (int16 wordPos, uint8 bitPos) = TickBitmap.position(_params.tickLower / key.tickSpacing);
266
        (int16 wordPosUpper, uint8 bitPosUpper) = TickBitmap.position(_params.tickUpper / key.tickSpacing);
267

                            
                        
268
        uint256 tickBitmap = StateLibrary.getTickBitmap(manager, poolId, wordPos);
269
        assertNotEq(tickBitmap, 0);
270

                            
                        
271
        // in fuzz tests, the tickLower and tickUpper might exist on the same word
272
        if (wordPos == wordPosUpper) {
273
            assertEq(tickBitmap, (1 << bitPos) | (1 << bitPosUpper));
274
        } else {
275
            assertEq(tickBitmap, 1 << bitPos);
276
        }
277
    }
278

                            
                        
279
    function test_getPositionInfo() public {
280
        // create liquidity
281
        modifyLiquidityRouter.modifyLiquidity(
282
            key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES
283
        );
284

                            
                        
285
        // swap to create fees, crossing a tick
286
        uint256 swapAmount = 10 ether;
287
        swap(key, true, -int256(swapAmount), ZERO_BYTES);
288
        (, int24 currentTick,,) = StateLibrary.getSlot0(manager, poolId);
289
        assertNotEq(currentTick, -139);
290

                            
                        
291
        // poke the LP so that fees are updated
292
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 0, 0), ZERO_BYTES);
293

                            
                        
294
        bytes32 positionId =
295
            keccak256(abi.encodePacked(address(modifyLiquidityRouter), int24(-60), int24(60), bytes32(0)));
296

                            
                        
297
        (uint128 liquidity, uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) =
298
            StateLibrary.getPositionInfo(manager, poolId, positionId);
299
        snapLastCall("extsload getPositionInfo");
300

                            
                        
301
        assertEq(liquidity, 10_000 ether);
302

                            
                        
303
        assertNotEq(feeGrowthInside0X128, 0);
304
        assertEq(feeGrowthInside1X128, 0);
305
    }
306

                            
                        
307
    function test_fuzz_getPositionInfo(
308
        IPoolManager.ModifyLiquidityParams memory params,
309
        uint256 swapAmount,
310
        bool zeroForOne
311
    ) public {
312
        (IPoolManager.ModifyLiquidityParams memory _params, BalanceDelta delta) =
313
            createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES);
314

                            
                        
315
        uint256 delta0 = uint256(int256(-delta.amount0()));
316
        uint256 delta1 = uint256(int256(-delta.amount1()));
317
        // if one of the deltas is zero, ensure to swap in the right direction
318
        if (delta0 == 0) {
319
            zeroForOne = true;
320
        } else if (delta1 == 0) {
321
            zeroForOne = false;
322
        }
323
        swapAmount = bound(swapAmount, 1, uint256(int256(type(int128).max)));
324
        swap(key, zeroForOne, -int256(swapAmount), ZERO_BYTES);
325

                            
                        
326
        // poke the LP so that fees are updated
327
        modifyLiquidityRouter.modifyLiquidity(
328
            key, IPoolManager.ModifyLiquidityParams(_params.tickLower, _params.tickUpper, 0, 0), ZERO_BYTES
329
        );
330

                            
                        
331
        bytes32 positionId = keccak256(
332
            abi.encodePacked(address(modifyLiquidityRouter), _params.tickLower, _params.tickUpper, bytes32(0))
333
        );
334

                            
                        
335
        (uint128 liquidity, uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) =
336
            StateLibrary.getPositionInfo(manager, poolId, positionId);
337

                            
                        
338
        assertEq(liquidity, uint128(uint256(_params.liquidityDelta)));
339
        if (zeroForOne) {
340
            assertNotEq(feeGrowthInside0X128, 0);
341
            assertEq(feeGrowthInside1X128, 0);
342
        } else {
343
            assertEq(feeGrowthInside0X128, 0);
344
            assertNotEq(feeGrowthInside1X128, 0);
345
        }
346
    }
347

                            
                        
348
    function test_getTickFeeGrowthOutside() public {
349
        // create liquidity
350
        modifyLiquidityRouter.modifyLiquidity(
351
            key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES
352
        );
353

                            
                        
354
        modifyLiquidityRouter.modifyLiquidity(
355
            key, IPoolManager.ModifyLiquidityParams(-600, 600, 10_000 ether, 0), ZERO_BYTES
356
        );
357

                            
                        
358
        // swap to create fees, crossing a tick
359
        uint256 swapAmount = 100 ether;
360
        swap(key, true, -int256(swapAmount), ZERO_BYTES);
361
        (, int24 currentTick,,) = StateLibrary.getSlot0(manager, poolId);
362
        assertEq(currentTick, -139);
363

                            
                        
364
        int24 tick = -60;
365
        (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128) =
366
            StateLibrary.getTickFeeGrowthOutside(manager, poolId, tick);
367
        snapLastCall("extsload getTickFeeGrowthOutside");
368

                            
                        
369
        // magic number verified against a native getter on PoolManager
370
        assertEq(feeGrowthOutside0X128, 3076214778951936192155253373200636);
371
        assertEq(feeGrowthOutside1X128, 0);
372

                            
                        
373
        tick = 60;
374
        (feeGrowthOutside0X128, feeGrowthOutside1X128) = StateLibrary.getTickFeeGrowthOutside(manager, poolId, tick);
375
        assertEq(feeGrowthOutside0X128, 0);
376
        assertEq(feeGrowthOutside1X128, 0);
377
    }
378

                            
                        
379
    // also hard to fuzz because of feeGrowthOutside
380
    function test_getTickInfo() public {
381
        // create liquidity
382
        modifyLiquidityRouter.modifyLiquidity(
383
            key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES
384
        );
385

                            
                        
386
        modifyLiquidityRouter.modifyLiquidity(
387
            key, IPoolManager.ModifyLiquidityParams(-600, 600, 10_000 ether, 0), ZERO_BYTES
388
        );
389

                            
                        
390
        // swap to create fees, crossing a tick
391
        uint256 swapAmount = 100 ether;
392
        swap(key, true, -int256(swapAmount), ZERO_BYTES);
393
        (, int24 currentTick,,) = StateLibrary.getSlot0(manager, poolId);
394
        assertEq(currentTick, -139);
395

                            
                        
396
        int24 tick = -60;
397
        (uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128) =
398
            StateLibrary.getTickInfo(manager, poolId, tick);
399
        snapLastCall("extsload getTickInfo");
400

                            
                        
401
        (uint128 liquidityGross_, int128 liquidityNet_) = StateLibrary.getTickLiquidity(manager, poolId, tick);
402
        (uint256 feeGrowthOutside0X128_, uint256 feeGrowthOutside1X128_) =
403
            StateLibrary.getTickFeeGrowthOutside(manager, poolId, tick);
404

                            
                        
405
        assertEq(liquidityGross, 10_000 ether);
406
        assertEq(liquidityGross, liquidityGross_);
407
        assertEq(liquidityNet, liquidityNet_);
408

                            
                        
409
        assertNotEq(feeGrowthOutside0X128, 0);
410
        assertEq(feeGrowthOutside1X128, 0);
411
        assertEq(feeGrowthOutside0X128, feeGrowthOutside0X128_);
412
        assertEq(feeGrowthOutside1X128, feeGrowthOutside1X128_);
413
    }
414

                            
                        
415
    function test_getFeeGrowthInside() public {
416
        // create liquidity
417
        modifyLiquidityRouter.modifyLiquidity(
418
            key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES
419
        );
420

                            
                        
421
        modifyLiquidityRouter.modifyLiquidity(
422
            key, IPoolManager.ModifyLiquidityParams(-600, 600, 10_000 ether, 0), ZERO_BYTES
423
        );
424

                            
                        
425
        // swap to create fees, crossing a tick
426
        uint256 swapAmount = 100 ether;
427
        swap(key, true, -int256(swapAmount), ZERO_BYTES);
428
        (, int24 currentTick,,) = StateLibrary.getSlot0(manager, poolId);
429
        assertEq(currentTick, -139);
430

                            
                        
431
        // calculated live
432
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) =
433
            StateLibrary.getFeeGrowthInside(manager, poolId, -60, 60);
434
        snapLastCall("extsload getFeeGrowthInside");
435

                            
                        
436
        // poke the LP so that fees are updated
437
        modifyLiquidityRouter.modifyLiquidity(key, IPoolManager.ModifyLiquidityParams(-60, 60, 0, 0), ZERO_BYTES);
438

                            
                        
439
        bytes32 positionId =
440
            keccak256(abi.encodePacked(address(modifyLiquidityRouter), int24(-60), int24(60), bytes32(0)));
441

                            
                        
442
        (, uint256 feeGrowthInside0X128_, uint256 feeGrowthInside1X128_) =
443
            StateLibrary.getPositionInfo(manager, poolId, positionId);
444

                            
                        
445
        assertNotEq(feeGrowthInside0X128, 0);
446
        assertEq(feeGrowthInside0X128, feeGrowthInside0X128_);
447
        assertEq(feeGrowthInside1X128, feeGrowthInside1X128_);
448
    }
449

                            
                        
450
    function test_fuzz_getFeeGrowthInside(IPoolManager.ModifyLiquidityParams memory params, bool zeroForOne) public {
451
        modifyLiquidityRouter.modifyLiquidity(
452
            key,
453
            IPoolManager.ModifyLiquidityParams(
454
                TickMath.minUsableTick(key.tickSpacing), TickMath.maxUsableTick(key.tickSpacing), 10_000 ether, 0
455
            ),
456
            ZERO_BYTES
457
        );
458

                            
                        
459
        (IPoolManager.ModifyLiquidityParams memory _params,) =
460
            createFuzzyLiquidity(modifyLiquidityRouter, key, params, SQRT_PRICE_1_1, ZERO_BYTES);
461

                            
                        
462
        swap(key, zeroForOne, -int256(100e18), ZERO_BYTES);
463

                            
                        
464
        // calculated live
465
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) =
466
            StateLibrary.getFeeGrowthInside(manager, poolId, _params.tickLower, _params.tickUpper);
467

                            
                        
468
        // poke the LP so that fees are updated
469
        modifyLiquidityRouter.modifyLiquidity(
470
            key, IPoolManager.ModifyLiquidityParams(_params.tickLower, _params.tickUpper, 0, 0), ZERO_BYTES
471
        );
472
        bytes32 positionId = keccak256(
473
            abi.encodePacked(address(modifyLiquidityRouter), _params.tickLower, _params.tickUpper, bytes32(0))
474
        );
475

                            
                        
476
        (, uint256 feeGrowthInside0X128_, uint256 feeGrowthInside1X128_) =
477
            StateLibrary.getPositionInfo(manager, poolId, positionId);
478

                            
                        
479
        assertEq(feeGrowthInside0X128, feeGrowthInside0X128_);
480
        assertEq(feeGrowthInside1X128, feeGrowthInside1X128_);
481
    }
482

                            
                        
483
    function test_getPositionLiquidity() public {
484
        // create liquidity
485
        modifyLiquidityRouter.modifyLiquidity(
486
            key, IPoolManager.ModifyLiquidityParams(-60, 60, 10_000 ether, 0), ZERO_BYTES
487
        );
488

                            
                        
489
        bytes32 positionId =
490
            keccak256(abi.encodePacked(address(modifyLiquidityRouter), int24(-60), int24(60), bytes32(0)));
491

                            
                        
492
        uint128 liquidity = StateLibrary.getPositionLiquidity(manager, poolId, positionId);
493
        snapLastCall("extsload getPositionLiquidity");
494

                            
                        
495
        assertEq(liquidity, 10_000 ether);
496
    }
497

                            
                        
498
    function test_fuzz_getPositionLiquidity(
499
        IPoolManager.ModifyLiquidityParams memory paramsA,
500
        IPoolManager.ModifyLiquidityParams memory paramsB
501
    ) public {
502
        (IPoolManager.ModifyLiquidityParams memory _paramsA) =
503
            Fuzzers.createFuzzyLiquidityParams(key, paramsA, SQRT_PRICE_1_1);
504

                            
                        
505
        (IPoolManager.ModifyLiquidityParams memory _paramsB) =
506
            Fuzzers.createFuzzyLiquidityParams(key, paramsB, SQRT_PRICE_1_1);
507

                            
                        
508
        // Assume there are no overlapping positions
509
        vm.assume(
510
            _paramsA.tickLower != _paramsB.tickLower && _paramsA.tickLower != _paramsB.tickUpper
511
                && _paramsB.tickLower != _paramsA.tickUpper && _paramsA.tickUpper != _paramsB.tickUpper
512
        );
513

                            
                        
514
        modifyLiquidityRouter.modifyLiquidity(key, _paramsA, ZERO_BYTES);
515
        modifyLiquidityRouter.modifyLiquidity(key, _paramsB, ZERO_BYTES);
516

                            
                        
517
        bytes32 positionIdA = keccak256(
518
            abi.encodePacked(address(modifyLiquidityRouter), _paramsA.tickLower, _paramsA.tickUpper, bytes32(0))
519
        );
520
        uint128 liquidityA = StateLibrary.getPositionLiquidity(manager, poolId, positionIdA);
521
        assertEq(liquidityA, uint128(uint256(_paramsA.liquidityDelta)));
522

                            
                        
523
        bytes32 positionIdB = keccak256(
524
            abi.encodePacked(address(modifyLiquidityRouter), _paramsB.tickLower, _paramsB.tickUpper, bytes32(0))
525
        );
526
        uint128 liquidityB = StateLibrary.getPositionLiquidity(manager, poolId, positionIdB);
527
        assertEq(liquidityB, uint128(uint256(_paramsB.liquidityDelta)));
528
    }
529
}
530

                            
                        

Lines covered: 0 / 146 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Vm} from "forge-std/Vm.sol";
6
import {SqrtPriceMath} from "../../src/libraries/SqrtPriceMath.sol";
7
import {SwapMath} from "../../src/libraries/SwapMath.sol";
8
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
9

                            
                        
10
contract SwapMathTest is Test, GasSnapshot {
11
    uint160 private constant SQRT_PRICE_1_1 = 79228162514264337593543950336;
12
    uint160 private constant SQRT_PRICE_99_100 = 78831026366734652303669917531;
13
    uint160 private constant SQRT_PRICE_99_1000 = 24928559360766947368818086097;
14
    uint160 private constant SQRT_PRICE_101_100 = 79623317895830914510639640423;
15
    uint160 private constant SQRT_PRICE_1000_100 = 250541448375047931186413801569;
16
    uint160 private constant SQRT_PRICE_1010_100 = 251791039410471229173201122529;
17
    uint160 private constant SQRT_PRICE_10000_100 = 792281625142643375935439503360;
18

                            
                        
19
    function test_fuzz_getSqrtPriceTarget(bool zeroForOne, uint160 sqrtPriceNextX96, uint160 sqrtPriceLimitX96)
20
        public
21
        pure
22
    {
23
        assertEq(
24
            SwapMath.getSqrtPriceTarget(zeroForOne, sqrtPriceNextX96, sqrtPriceLimitX96),
25
            (zeroForOne ? sqrtPriceNextX96 < sqrtPriceLimitX96 : sqrtPriceNextX96 > sqrtPriceLimitX96)
26
                ? sqrtPriceLimitX96
27
                : sqrtPriceNextX96
28
        );
29
    }
30

                            
                        
31
    function test_computeSwapStep_exactAmountIn_oneForZero_thatGetsCappedAtPriceTargetIn() public pure {
32
        uint160 priceTarget = SQRT_PRICE_101_100;
33
        uint160 price = SQRT_PRICE_1_1;
34
        uint128 liquidity = 2 ether;
35
        int256 amount = (1 ether) * -1;
36
        uint24 lpFee = 600;
37
        bool zeroForOne = false;
38

                            
                        
39
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
40
            SwapMath.computeSwapStep(price, priceTarget, liquidity, amount, lpFee);
41

                            
                        
42
        assertEq(amountIn, 9975124224178055);
43
        assertEq(amountOut, 9925619580021728);
44
        assertEq(feeAmount, 5988667735148);
45
        assert(amountIn + feeAmount < uint256(amount * -1));
46

                            
                        
47
        uint256 priceAfterWholeInputAmount =
48
            SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, uint256(amount * -1), zeroForOne);
49

                            
                        
50
        assertEq(sqrtQ, priceTarget);
51
        assert(sqrtQ < priceAfterWholeInputAmount);
52
    }
53

                            
                        
54
    function test_computeSwapStep_exactAmountOut_oneForZero_thatGetsCappedAtPriceTargetIn() public pure {
55
        uint160 priceTarget = SQRT_PRICE_101_100;
56
        uint160 price = SQRT_PRICE_1_1;
57
        uint128 liquidity = 2 ether;
58
        int256 amount = 1 ether;
59
        uint24 lpFee = 600;
60
        bool zeroForOne = false;
61

                            
                        
62
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
63
            SwapMath.computeSwapStep(price, priceTarget, liquidity, amount, lpFee);
64

                            
                        
65
        assertEq(amountIn, 9975124224178055);
66
        assertEq(amountOut, 9925619580021728);
67
        assertEq(feeAmount, 5988667735148);
68
        assert(amountOut < uint256(amount));
69

                            
                        
70
        uint256 priceAfterWholeOutputAmount =
71
            SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, uint256(amount), zeroForOne);
72

                            
                        
73
        assertEq(sqrtQ, priceTarget);
74
        assert(sqrtQ < priceAfterWholeOutputAmount);
75
    }
76

                            
                        
77
    function test_computeSwapStep_exactAmountIn_oneForZero_thatIsFullySpentIn() public pure {
78
        uint160 priceTarget = SQRT_PRICE_1000_100;
79
        uint160 price = SQRT_PRICE_1_1;
80
        uint128 liquidity = 2 ether;
81
        int256 amount = 1 ether * -1;
82
        uint24 lpFee = 600;
83
        bool zeroForOne = false;
84

                            
                        
85
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
86
            SwapMath.computeSwapStep(price, priceTarget, liquidity, amount, lpFee);
87

                            
                        
88
        assertEq(amountIn, 999400000000000000);
89
        assertEq(amountOut, 666399946655997866);
90
        assertEq(feeAmount, 600000000000000);
91
        assertEq(amountIn + feeAmount, uint256(-amount));
92

                            
                        
93
        uint256 priceAfterWholeInputAmountLessFee =
94
            SqrtPriceMath.getNextSqrtPriceFromInput(price, liquidity, uint256(uint256(-amount) - feeAmount), zeroForOne);
95

                            
                        
96
        assert(sqrtQ < priceTarget);
97
        assertEq(sqrtQ, priceAfterWholeInputAmountLessFee);
98
    }
99

                            
                        
100
    function test_computeSwapStep_exactAmountOut_oneForZero_thatIsFullyReceivedIn() public pure {
101
        uint160 priceTarget = SQRT_PRICE_10000_100;
102
        uint160 price = SQRT_PRICE_1_1;
103
        uint128 liquidity = 2 ether;
104
        int256 amount = (1 ether);
105
        uint24 lpFee = 600;
106
        bool zeroForOne = false;
107

                            
                        
108
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
109
            SwapMath.computeSwapStep(price, priceTarget, liquidity, amount, lpFee);
110

                            
                        
111
        assertEq(amountIn, 2000000000000000000);
112
        assertEq(feeAmount, 1200720432259356);
113
        assertEq(amountOut, uint256(amount));
114

                            
                        
115
        uint256 priceAfterWholeOutputAmount =
116
            SqrtPriceMath.getNextSqrtPriceFromOutput(price, liquidity, uint256(amount), zeroForOne);
117

                            
                        
118
        assert(sqrtQ < priceTarget);
119
        assertEq(sqrtQ, priceAfterWholeOutputAmount);
120
    }
121

                            
                        
122
    function test_computeSwapStep_amountOut_isCappedAtTheDesiredAmountOut() public pure {
123
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) = SwapMath.computeSwapStep(
124
            417332158212080721273783715441582, 1452870262520218020823638996, 159344665391607089467575320103, 1, 1
125
        );
126

                            
                        
127
        assertEq(amountIn, 1);
128
        assertEq(feeAmount, 1);
129
        assertEq(amountOut, 1); // would be 2 if not capped
130
        assertEq(sqrtQ, 417332158212080721273783715441581);
131
    }
132

                            
                        
133
    function test_computeSwapStep_targetPriceOf1UsesPartialInputAmount() public pure {
134
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
135
            SwapMath.computeSwapStep(2, 1, 1, -3915081100057732413702495386755767, 1);
136
        assertEq(amountIn, 39614081257132168796771975168);
137
        assertEq(feeAmount, 39614120871253040049813);
138
        assert(amountIn + feeAmount <= 3915081100057732413702495386755767);
139
        assertEq(amountOut, 0);
140
        assertEq(sqrtQ, 1);
141
    }
142

                            
                        
143
    function test_computeSwapStep_entireInputAmountTakenAsFee() public pure {
144
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
145
            SwapMath.computeSwapStep(2413, 79887613182836312, 1985041575832132834610021537970, -10, 1872);
146

                            
                        
147
        assertEq(amountIn, 0);
148
        assertEq(feeAmount, 10);
149
        assertEq(amountOut, 0);
150
        assertEq(sqrtQ, 2413);
151
    }
152

                            
                        
153
    function test_computeSwapStep_zeroForOne_handlesIntermediateInsufficientLiquidityInExactOutputCase() public pure {
154
        uint160 sqrtP = 20282409603651670423947251286016;
155
        uint160 sqrtPTarget = (sqrtP * 11) / 10;
156
        uint128 liquidity = 1024;
157
        // virtual reserves of one are only 4
158
        // https://www.wolframalpha.com/input/?i=1024+%2F+%2820282409603651670423947251286016+%2F+2**96%29
159
        int256 amountRemaining = 4;
160
        uint24 feePips = 3000;
161

                            
                        
162
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
163
            SwapMath.computeSwapStep(sqrtP, sqrtPTarget, liquidity, amountRemaining, feePips);
164

                            
                        
165
        assertEq(amountOut, 0);
166
        assertEq(sqrtQ, sqrtPTarget);
167
        assertEq(amountIn, 26215);
168
        assertEq(feeAmount, 79);
169
    }
170

                            
                        
171
    function test_computeSwapStep_oneForZero_handlesIntermediateInsufficientLiquidityInExactOutputCase() public pure {
172
        uint160 sqrtP = 20282409603651670423947251286016;
173
        uint160 sqrtPTarget = (sqrtP * 9) / 10;
174
        uint128 liquidity = 1024;
175
        // virtual reserves of zero are only 262144
176
        // https://www.wolframalpha.com/input/?i=1024+*+%2820282409603651670423947251286016+%2F+2**96%29
177
        int256 amountRemaining = 263000;
178
        uint24 feePips = 3000;
179

                            
                        
180
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
181
            SwapMath.computeSwapStep(sqrtP, sqrtPTarget, liquidity, amountRemaining, feePips);
182

                            
                        
183
        assertEq(amountOut, 26214);
184
        assertEq(sqrtQ, sqrtPTarget);
185
        assertEq(amountIn, 1);
186
        assertEq(feeAmount, 1);
187
    }
188

                            
                        
189
    function test_fuzz_computeSwapStep(
190
        uint160 sqrtPriceRaw,
191
        uint160 sqrtPriceTargetRaw,
192
        uint128 liquidity,
193
        int256 amountRemaining,
194
        uint24 feePips
195
    ) public pure {
196
        vm.assume(sqrtPriceRaw > 0);
197
        vm.assume(sqrtPriceTargetRaw > 0);
198
        vm.assume(feePips >= 0);
199

                            
                        
200
        if (amountRemaining >= 0) {
201
            vm.assume(feePips < 1e6);
202
        } else {
203
            vm.assume(feePips <= 1e6);
204
        }
205

                            
                        
206
        (uint160 sqrtQ, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
207
            SwapMath.computeSwapStep(sqrtPriceRaw, sqrtPriceTargetRaw, liquidity, amountRemaining, feePips);
208

                            
                        
209
        assertLe(amountIn, type(uint256).max - feeAmount);
210

                            
                        
211
        unchecked {
212
            if (amountRemaining >= 0) {
213
                assertLe(amountOut, uint256(amountRemaining));
214
            } else {
215
                assertLe(amountIn + feeAmount, uint256(-amountRemaining));
216
            }
217
        }
218

                            
                        
219
        if (sqrtPriceRaw == sqrtPriceTargetRaw) {
220
            assertEq(amountIn, 0);
221
            assertEq(amountOut, 0);
222
            assertEq(feeAmount, 0);
223
            assertEq(sqrtQ, sqrtPriceTargetRaw);
224
        }
225

                            
                        
226
        // didn't reach price target, entire amount must be consumed
227
        if (sqrtQ != sqrtPriceTargetRaw) {
228
            uint256 absAmtRemaining;
229
            if (amountRemaining == type(int256).min) {
230
                absAmtRemaining = uint256(type(int256).max) + 1;
231
            } else if (amountRemaining < 0) {
232
                absAmtRemaining = uint256(-amountRemaining);
233
            } else {
234
                absAmtRemaining = uint256(amountRemaining);
235
            }
236
            if (amountRemaining > 0) assertEq(amountOut, absAmtRemaining);
237
            else assertEq(amountIn + feeAmount, absAmtRemaining);
238
        }
239

                            
                        
240
        // next price is between price and price target
241
        if (sqrtPriceTargetRaw <= sqrtPriceRaw) {
242
            assertLe(sqrtQ, sqrtPriceRaw);
243
            assertGe(sqrtQ, sqrtPriceTargetRaw);
244
        } else {
245
            assertGe(sqrtQ, sqrtPriceRaw);
246
            assertLe(sqrtQ, sqrtPriceTargetRaw);
247
        }
248
    }
249

                            
                        
250
    function test_computeSwapStep_swapOneForZero_exactInCapped() public {
251
        snapStart("SwapMath_oneForZero_exactInCapped");
252
        SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_101_100, 2 ether, (1 ether) * -1, 600);
253
        snapEnd();
254
    }
255

                            
                        
256
    function test_computeSwapStep_swapZeroForOne_exactInCapped() public {
257
        snapStart("SwapMath_zeroForOne_exactInCapped");
258
        SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_99_100, 2 ether, (1 ether) * -1, 600);
259
        snapEnd();
260
    }
261

                            
                        
262
    function test_computeSwapStep_swapOneForZero_exactOutCapped() public {
263
        snapStart("SwapMath_oneForZero_exactOutCapped");
264
        SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_101_100, 2 ether, 1 ether, 600);
265
        snapEnd();
266
    }
267

                            
                        
268
    function test_computeSwapStep_swapZeroForOne_exactOutCapped() public {
269
        snapStart("SwapMath_zeroForOne_exactOutCapped");
270
        SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_99_100, 2 ether, 1 ether, 600);
271
        snapEnd();
272
    }
273

                            
                        
274
    function test_computeSwapStep_swapOneForZero_exactInPartial() public {
275
        snapStart("SwapMath_oneForZero_exactInPartial");
276
        SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_1010_100, 2 ether, 1_000 * -1, 600);
277
        snapEnd();
278
    }
279

                            
                        
280
    function test_computeSwapStep_swapZeroForOne_exactInPartial() public {
281
        snapStart("SwapMath_zeroForOne_exactInPartial");
282
        SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_99_1000, 2 ether, 1_000 * -1, 600);
283
        snapEnd();
284
    }
285

                            
                        
286
    function test_computeSwapStep_swapOneForZero_exactOutPartial() public {
287
        snapStart("SwapMath_oneForZero_exactOutPartial");
288
        SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_1010_100, 2 ether, 1_000, 600);
289
        snapEnd();
290
    }
291

                            
                        
292
    function test_computeSwapStep_swapZeroForOne_exactOutPartial() public {
293
        snapStart("SwapMath_zeroForOne_exactOutPartial");
294
        SwapMath.computeSwapStep(SQRT_PRICE_1_1, SQRT_PRICE_99_1000, 2 ether, 1_000, 600);
295
        snapEnd();
296
    }
297
}
298

                            
                        

Lines covered: 0 / 138 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Vm} from "forge-std/Vm.sol";
6
import {GasSnapshot} from "lib/forge-gas-snapshot/src/GasSnapshot.sol";
7
import {TickBitmap} from "../../src/libraries/TickBitmap.sol";
8
import {TickMath} from "../../src/libraries/TickMath.sol";
9

                            
                        
10
contract TickBitmapTest is Test, GasSnapshot {
11
    using TickBitmap for mapping(int16 => uint256);
12

                            
                        
13
    int24 constant INITIALIZED_TICK = 70;
14
    int24 constant TICK_IN_UNINITIALZIED_WORD = 10000;
15
    int24 constant SOLO_INITIALIZED_TICK_IN_WORD = -10000;
16

                            
                        
17
    mapping(int16 => uint256) public bitmap;
18
    mapping(int16 => uint256) internal emptyBitmap;
19

                            
                        
20
    function setUp() public {
21
        // set dirty slots beforehand for certain gas tests
22
        int24[10] memory ticks = [SOLO_INITIALIZED_TICK_IN_WORD, -200, -55, -4, INITIALIZED_TICK, 78, 84, 139, 240, 535];
23
        for (uint256 i; i < ticks.length - 1; i++) {
24
            flipTick(ticks[i]);
25
        }
26
    }
27

                            
                        
28
    function test_fuzz_compress(int24 tick, int24 tickSpacing) public pure {
29
        tickSpacing = int24(bound(tickSpacing, 1, type(int24).max));
30
        int24 compressed = tick / tickSpacing;
31
        if (tick < 0 && tick % tickSpacing != 0) compressed--;
32
        assertEq(TickBitmap.compress(tick, tickSpacing), compressed);
33
    }
34

                            
                        
35
    function test_fuzz_position(int24 tick) public pure {
36
        (int16 wordPos, uint8 bitPos) = TickBitmap.position(tick);
37
        assertEq(wordPos, tick >> 8);
38
        assertEq(bitPos, uint8(int8(tick % 256)));
39
    }
40

                            
                        
41
    function test_isInitialized_isFalseAtFirst() public view {
42
        assertEq(isInitialized(1), false);
43
    }
44

                            
                        
45
    function test_isInitialized_isFlippedByFlipTick() public {
46
        flipTick(1);
47
        assertEq(isInitialized(1), true);
48
    }
49

                            
                        
50
    function test_isInitialized_isFlippedBackByFlipTick() public {
51
        flipTick(1);
52
        flipTick(1);
53
        assertEq(isInitialized(1), false);
54
    }
55

                            
                        
56
    function test_isInitialized_isNotChangedByAnotherFlipToADifferentTick() public {
57
        flipTick(2);
58
        assertEq(isInitialized(1), false);
59
    }
60

                            
                        
61
    function test_isInitialized_isNotChangedByAnotherFlipToADifferentTickOnAnotherWord() public {
62
        flipTick(1 + 256);
63
        assertEq(isInitialized(257), true);
64
        assertEq(isInitialized(1), false);
65
    }
66

                            
                        
67
    function test_flipTick_flipsOnlyTheSpecifiedTick() public {
68
        flipTick(-230);
69
        assertEq(isInitialized(-230), true);
70
        assertEq(isInitialized(-231), false);
71
        assertEq(isInitialized(-229), false);
72
        assertEq(isInitialized(-230 + 256), false);
73
        assertEq(isInitialized(-230 - 256), false);
74

                            
                        
75
        flipTick(-230);
76
        assertEq(isInitialized(-230), false);
77
        assertEq(isInitialized(-231), false);
78
        assertEq(isInitialized(-229), false);
79
        assertEq(isInitialized(-230 + 256), false);
80
        assertEq(isInitialized(-230 - 256), false);
81

                            
                        
82
        assertEq(isInitialized(1), false);
83
    }
84

                            
                        
85
    function test_flipTick_revertsOnlyItself() public {
86
        flipTick(-230);
87
        flipTick(-259);
88
        flipTick(-229);
89
        flipTick(500);
90
        flipTick(-259);
91
        flipTick(-229);
92
        flipTick(-259);
93
        assertEq(isInitialized(-259), true);
94
        assertEq(isInitialized(-229), false);
95
    }
96

                            
                        
97
    function test_flipTick_flippingFirstTickInWordToInitialized_gas() public {
98
        snapStart("flipTick_flippingFirstTickInWordToInitialized");
99
        flipTick(TICK_IN_UNINITIALZIED_WORD);
100
        snapEnd();
101
    }
102

                            
                        
103
    function test_flipTick_flippingSecondTickInWordToInitialized_gas() public {
104
        snapStart("flipTick_flippingSecondTickInWordToInitialized");
105
        flipTick(INITIALIZED_TICK + 1);
106
        snapEnd();
107
    }
108

                            
                        
109
    function test_flipTick_flippingATickThatResultsInDeletingAWord_gas() public {
110
        snapStart("flipTick_flippingATickThatResultsInDeletingAWord");
111
        flipTick(SOLO_INITIALIZED_TICK_IN_WORD);
112
        snapEnd();
113
    }
114

                            
                        
115
    function test_fuzz_flipTick(int24 tick, int24 tickSpacing) public {
116
        tickSpacing = int24(bound(tickSpacing, 1, type(int24).max));
117

                            
                        
118
        if (tick % tickSpacing != 0) {
119
            vm.expectRevert(abi.encodeWithSelector(TickBitmap.TickMisaligned.selector, tick, tickSpacing));
120
            bitmap.flipTick(tick, tickSpacing);
121
        } else {
122
            bool initialized = isInitialized(tick, tickSpacing);
123
            bitmap.flipTick(tick, tickSpacing);
124
            assertEq(isInitialized(tick, tickSpacing), !initialized);
125
            // flip again
126
            bitmap.flipTick(tick, tickSpacing);
127
            assertEq(isInitialized(tick, tickSpacing), initialized);
128
        }
129
    }
130

                            
                        
131
    function test_nextInitializedTickWithinOneWord_lteFalse_returnsTickToRightIfAtInitializedTick() public view {
132
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(78, 1, false);
133
        assertEq(next, 84);
134
        assertEq(initialized, true);
135
    }
136

                            
                        
137
    function test_nextInitializedTickWithinOneWord_lteFalse_returnsTickToRightIfAtInitializedTick2() public view {
138
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(-55, 1, false);
139

                            
                        
140
        assertEq(next, -4);
141
        assertEq(initialized, true);
142
    }
143

                            
                        
144
    function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheTickDirectlyToTheRight() public view {
145
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(77, 1, false);
146
        assertEq(next, 78);
147
        assertEq(initialized, true);
148
    }
149

                            
                        
150
    function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheTickDirectlyToTheRight2() public view {
151
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(-56, 1, false);
152
        assertEq(next, -55);
153
        assertEq(initialized, true);
154
    }
155

                            
                        
156
    function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheNextWordsInitializedTickIfOnTheRightBoundary()
157
        public
158
        view
159
    {
160
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(255, 1, false);
161
        assertEq(next, 511);
162
        assertEq(initialized, false);
163
    }
164

                            
                        
165
    function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheNextWordsInitializedTickIfOnTheRightBoundary2()
166
        public
167
        view
168
    {
169
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(-257, 1, false);
170
        assertEq(next, -200);
171
        assertEq(initialized, true);
172
    }
173

                            
                        
174
    function test_nextInitializedTickWithinOneWord_lteFalse_returnsTheNextInitializedTickFromTheNextWord() public {
175
        flipTick(340);
176

                            
                        
177
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(328, 1, false);
178
        assertEq(next, 340);
179
        assertEq(initialized, true);
180
    }
181

                            
                        
182
    function test_nextInitializedTickWithinOneWord_lteFalse_doesNotExceedBoundary() public view {
183
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(508, 1, false);
184
        assertEq(next, 511);
185
        assertEq(initialized, false);
186
    }
187

                            
                        
188
    function test_nextInitializedTickWithinOneWord_lteFalse_skipsEntireWord() public view {
189
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(255, 1, false);
190
        assertEq(next, 511);
191
        assertEq(initialized, false);
192
    }
193

                            
                        
194
    function test_nextInitializedTickWithinOneWord_lteFalse_skipsHalfWord() public view {
195
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(383, 1, false);
196
        assertEq(next, 511);
197
        assertEq(initialized, false);
198
    }
199

                            
                        
200
    function test_nextInitializedTickWithinOneWord_lteFalse_onBoundary_gas() public {
201
        snapStart("nextInitializedTickWithinOneWord_lteFalse_onBoundary");
202
        bitmap.nextInitializedTickWithinOneWord(255, 1, false);
203
        snapEnd();
204
    }
205

                            
                        
206
    function test_nextInitializedTickWithinOneWord_lteFalse_justBelowBoundary_gas() public {
207
        snapStart("nextInitializedTickWithinOneWord_lteFalse_justBelowBoundary");
208
        bitmap.nextInitializedTickWithinOneWord(254, 1, false);
209
        snapEnd();
210
    }
211

                            
                        
212
    function test_nextInitializedTickWithinOneWord_lteFalse_forEntireWord_gas() public {
213
        snapStart("nextInitializedTickWithinOneWord_lteFalse_forEntireWord");
214
        bitmap.nextInitializedTickWithinOneWord(768, 1, false);
215
        snapEnd();
216
    }
217

                            
                        
218
    function test_nextInitializedTickWithinOneWord_lteTrue_returnsSameTickIfInitialized() public view {
219
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(78, 1, true);
220
        assertEq(next, 78);
221
        assertEq(initialized, true);
222
    }
223

                            
                        
224
    function test_nextInitializedTickWithinOneWord_lteTrue_returnsTickDirectlyToTheLeftOfInputTickIfNotInitialized()
225
        public
226
        view
227
    {
228
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(79, 1, true);
229
        assertEq(next, 78);
230
        assertEq(initialized, true);
231
    }
232

                            
                        
233
    function test_nextInitializedTickWithinOneWord_lteTrue_willNotExceedTheWordBoundary() public view {
234
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(258, 1, true);
235
        assertEq(next, 256);
236
        assertEq(initialized, false);
237
    }
238

                            
                        
239
    function test_nextInitializedTickWithinOneWord_lteTrue_atTheWordBoundary() public view {
240
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(256, 1, true);
241
        assertEq(next, 256);
242
        assertEq(initialized, false);
243
    }
244

                            
                        
245
    function test_nextInitializedTickWithinOneWord_lteTrue_wordBoundaryLess1nextInitializedTickInNextWord()
246
        public
247
        view
248
    {
249
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(72, 1, true);
250
        assertEq(next, 70);
251
        assertEq(initialized, true);
252
    }
253

                            
                        
254
    function test_nextInitializedTickWithinOneWord_lteTrue_wordBoundary() public view {
255
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(-257, 1, true);
256
        assertEq(next, -512);
257
        assertEq(initialized, false);
258
    }
259

                            
                        
260
    function test_nextInitializedTickWithinOneWord_lteTrue_entireEmptyWord() public view {
261
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(1023, 1, true);
262
        assertEq(next, 768);
263
        assertEq(initialized, false);
264
    }
265

                            
                        
266
    function test_nextInitializedTickWithinOneWord_lteTrue_halfwayThroughEmptyWord() public view {
267
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(900, 1, true);
268
        assertEq(next, 768);
269
        assertEq(initialized, false);
270
    }
271

                            
                        
272
    function test_nextInitializedTickWithinOneWord_lteTrue_boundaryIsInitialized() public {
273
        flipTick(329);
274
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(456, 1, true);
275
        assertEq(next, 329);
276
        assertEq(initialized, true);
277
    }
278

                            
                        
279
    function test_nextInitializedTickWithinOneWord_lteTrue_onBoundary_gas() public {
280
        snapStart("nextInitializedTickWithinOneWord_lteTrue_onBoundary_gas");
281
        bitmap.nextInitializedTickWithinOneWord(256, 1, true);
282
        snapEnd();
283
    }
284

                            
                        
285
    function test_nextInitializedTickWithinOneWord_lteTrue_justBelowBoundary_gas() public {
286
        snapStart("nextInitializedTickWithinOneWord_lteTrue_justBelowBoundary");
287
        bitmap.nextInitializedTickWithinOneWord(255, 1, true);
288
        snapEnd();
289
    }
290

                            
                        
291
    function test_nextInitializedTickWithinOneWord_lteTrue_forEntireWord_gas() public {
292
        snapStart("nextInitializedTickWithinOneWord_lteTrue_forEntireWord");
293
        bitmap.nextInitializedTickWithinOneWord(1024, 1, true);
294
        snapEnd();
295
    }
296

                            
                        
297
    function test_fuzz_nextInitializedTickWithinOneWord(int24 tick, bool lte) public view {
298
        // assume tick is at least one word inside type(int24).(max | min)
299
        vm.assume(lte ? tick >= -8388352 : tick < 8388351);
300

                            
                        
301
        (int24 next, bool initialized) = bitmap.nextInitializedTickWithinOneWord(tick, 1, lte);
302

                            
                        
303
        if (lte) {
304
            assertLe(next, tick);
305
            assertLe(tick - next, 256);
306
            // all the ticks between the input tick and the next tick should be uninitialized
307
            for (int24 i = tick; i > next; i--) {
308
                assertTrue(!isInitialized(i));
309
            }
310
            assertEq(isInitialized(next), initialized);
311
        } else {
312
            assertGt(next, tick);
313
            assertLe(next - tick, 256);
314
            // all the ticks between the input tick and the next tick should be uninitialized
315
            for (int24 i = tick + 1; i < next; i++) {
316
                assertTrue(!isInitialized(i));
317
            }
318
            assertEq(isInitialized(next), initialized);
319
        }
320
    }
321

                            
                        
322
    function test_fuzz_nextInitializedTickWithinOneWord_onEmptyBitmap(
323
        int24 tick,
324
        int24 tickSpacing,
325
        uint8 nextBitPos,
326
        bool lte
327
    ) public {
328
        tick = int24(bound(tick, TickMath.MIN_TICK, TickMath.MAX_TICK));
329
        tickSpacing = int24(bound(tickSpacing, TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING));
330
        int24 compressed = TickBitmap.compress(tick, tickSpacing);
331
        if (!lte) ++compressed;
332
        (int16 wordPos, uint8 bitPos) = TickBitmap.position(compressed);
333

                            
                        
334
        if (lte) {
335
            nextBitPos = uint8(bound(nextBitPos, 0, bitPos));
336
        } else {
337
            nextBitPos = uint8(bound(nextBitPos, bitPos, 255));
338
        }
339
        // Choose the next initialized tick within one word at random and flip it.
340
        int24 nextInitializedTick = ((int24(wordPos) << 8) + int24(uint24(nextBitPos))) * tickSpacing;
341
        emptyBitmap.flipTick(nextInitializedTick, tickSpacing);
342
        (int24 next, bool initialized) = emptyBitmap.nextInitializedTickWithinOneWord(tick, tickSpacing, lte);
343
        assertEq(initialized, true);
344
        assertEq(next, nextInitializedTick);
345
    }
346

                            
                        
347
    function isInitialized(int24 tick, int24 tickSpacing) internal view returns (bool) {
348
        unchecked {
349
            if (tick % tickSpacing != 0) return false;
350
            (int16 wordPos, uint8 bitPos) = TickBitmap.position(tick / tickSpacing);
351
            return bitmap[wordPos] & (1 << bitPos) != 0;
352
        }
353
    }
354

                            
                        
355
    function isInitialized(int24 tick) internal view returns (bool) {
356
        return isInitialized(tick, 1);
357
    }
358

                            
                        
359
    function flipTick(int24 tick) internal {
360
        bitmap.flipTick(tick, 1);
361
    }
362
}
363

                            
                        

Lines covered: 0 / 89 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
5
import {Test} from "forge-std/Test.sol";
6
import {Vm} from "forge-std/Vm.sol";
7
import {TickMathTest} from "src/test/TickMathTest.sol";
8
import {TickMath} from "src/libraries/TickMath.sol";
9
import {JavascriptFfi} from "test/utils/JavascriptFfi.sol";
10

                            
                        
11
contract TickMathTestTest is Test, JavascriptFfi, GasSnapshot {
12
    int24 constant MIN_TICK = -887272;
13
    int24 constant MAX_TICK = -MIN_TICK;
14

                            
                        
15
    uint160 constant MIN_SQRT_PRICE = 4295128739;
16
    uint160 constant MAX_SQRT_PRICE = 1461446703485210103287273052203988822378723970342;
17

                            
                        
18
    uint160 constant SQRT_PRICE_1_1 = 79228162514264337593543950336;
19

                            
                        
20
    uint256 constant ONE_PIP = 1e6;
21

                            
                        
22
    uint160[] getSqrtPriceAtTickFuzzResults;
23
    int24[] getTickAtSqrtPriceFuzzResults;
24

                            
                        
25
    TickMathTest tickMath;
26

                            
                        
27
    function setUp() public {
28
        tickMath = new TickMathTest();
29
        delete getSqrtPriceAtTickFuzzResults;
30
        delete getTickAtSqrtPriceFuzzResults;
31
    }
32

                            
                        
33
    function test_MIN_TICK_equalsNegativeMAX_TICK() public view {
34
        // this invariant is required in the Tick#tickSpacingToMaxLiquidityPerTick formula
35
        int24 minTick = tickMath.MIN_TICK();
36
        assertEq(minTick, tickMath.MAX_TICK() * -1);
37
        assertEq(minTick, MIN_TICK);
38
    }
39

                            
                        
40
    function test_MAX_TICK_equalsNegativeMIN_TICK() public view {
41
        // this invariant is required in the Tick#tickSpacingToMaxLiquidityPerTick formula
42
        // this test is redundant with the above MIN_TICK test
43
        int24 maxTick = tickMath.MAX_TICK();
44
        assertEq(maxTick, tickMath.MIN_TICK() * -1);
45
        assertEq(maxTick, MAX_TICK);
46
    }
47

                            
                        
48
    function test_getSqrtPriceAtTick_throwsForInt24Min() public {
49
        int24 tick = type(int24).min;
50
        vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidTick.selector, tick));
51
        tickMath.getSqrtPriceAtTick(tick);
52
    }
53

                            
                        
54
    function test_getSqrtPriceAtTick_throwsForTooLow() public {
55
        int24 tick = MIN_TICK - 1;
56
        vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidTick.selector, tick));
57
        tickMath.getSqrtPriceAtTick(tick);
58
    }
59

                            
                        
60
    function test_getSqrtPriceAtTick_throwsForTooHigh() public {
61
        int24 tick = MAX_TICK + 1;
62
        vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidTick.selector, tick));
63
        tickMath.getSqrtPriceAtTick(tick);
64
    }
65

                            
                        
66
    function test_fuzz_getSqrtPriceAtTick_throwsForTooLarge(int24 tick) public {
67
        if (tick > 0) {
68
            tick = int24(bound(tick, MAX_TICK + 1, type(int24).max));
69
        } else {
70
            tick = int24(bound(tick, type(int24).min, MIN_TICK - 1));
71
        }
72
        vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidTick.selector, tick));
73
        tickMath.getSqrtPriceAtTick(tick);
74
    }
75

                            
                        
76
    function test_getSqrtPriceAtTick_isValidMinTick() public view {
77
        assertEq(tickMath.getSqrtPriceAtTick(MIN_TICK), tickMath.MIN_SQRT_PRICE());
78
        assertEq(tickMath.getSqrtPriceAtTick(MIN_TICK), 4295128739);
79
    }
80

                            
                        
81
    function test_getSqrtPriceAtTick_isValidMinTickAddOne() public view {
82
        assertEq(tickMath.getSqrtPriceAtTick(MIN_TICK + 1), 4295343490);
83
    }
84

                            
                        
85
    function test_getSqrtPriceAtTick_isValidMaxTick() public view {
86
        assertEq(tickMath.getSqrtPriceAtTick(MAX_TICK), tickMath.MAX_SQRT_PRICE());
87
        assertEq(tickMath.getSqrtPriceAtTick(MAX_TICK), 1461446703485210103287273052203988822378723970342);
88
    }
89

                            
                        
90
    function test_getSqrtPriceAtTick_isValidMaxTickSubOne() public view {
91
        assertEq(tickMath.getSqrtPriceAtTick(MAX_TICK - 1), 1461373636630004318706518188784493106690254656249);
92
    }
93

                            
                        
94
    function test_getSqrtPriceAtTick_isLessThanJSImplMinTick() public view {
95
        // sqrt(1 / 2 ** 127) * 2 ** 96
96
        uint160 jsMinSqrtPrice = 6085630636;
97
        uint160 solMinSqrtPrice = tickMath.getSqrtPriceAtTick(MIN_TICK);
98
        assertLt(solMinSqrtPrice, jsMinSqrtPrice);
99
    }
100

                            
                        
101
    function test_getSqrtPriceAtTick_isGreaterThanJSImplMaxTick() public view {
102
        // sqrt(2 ** 127) * 2 ** 96
103
        uint160 jsMaxSqrtPrice = 1033437718471923706666374484006904511252097097914;
104
        uint160 solMaxSqrtPrice = tickMath.getSqrtPriceAtTick(MAX_TICK);
105
        assertGt(solMaxSqrtPrice, jsMaxSqrtPrice);
106
    }
107

                            
                        
108
    function test_getTickAtSqrtPrice_throwsForTooLow() public {
109
        uint160 sqrtPriceX96 = MIN_SQRT_PRICE - 1;
110
        vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96));
111
        tickMath.getTickAtSqrtPrice(sqrtPriceX96);
112
    }
113

                            
                        
114
    function test_getTickAtSqrtPrice_throwsForTooHigh() public {
115
        uint160 sqrtPriceX96 = MAX_SQRT_PRICE;
116
        vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96));
117
        tickMath.getTickAtSqrtPrice(sqrtPriceX96);
118
    }
119

                            
                        
120
    function test_fuzz_getTickAtSqrtPrice_throwsForInvalid(uint160 sqrtPriceX96, bool gte) public {
121
        if (gte) {
122
            sqrtPriceX96 = uint160(bound(sqrtPriceX96, MAX_SQRT_PRICE, type(uint160).max));
123
        } else {
124
            sqrtPriceX96 = uint160(bound(sqrtPriceX96, 0, MIN_SQRT_PRICE - 1));
125
        }
126
        vm.expectRevert(abi.encodeWithSelector(TickMath.InvalidSqrtPrice.selector, sqrtPriceX96));
127
        tickMath.getTickAtSqrtPrice(sqrtPriceX96);
128
    }
129

                            
                        
130
    function test_getTickAtSqrtPrice_isValidMinSqrtPrice() public view {
131
        assertEq(tickMath.getTickAtSqrtPrice(MIN_SQRT_PRICE), MIN_TICK);
132
    }
133

                            
                        
134
    function test_getTickAtSqrtPrice_isValidMinSqrtPricePlusOne() public view {
135
        assertEq(tickMath.getTickAtSqrtPrice(4295343490), MIN_TICK + 1);
136
    }
137

                            
                        
138
    function test_getTickAtSqrtPrice_isValidPriceClosestToMaxTick() public view {
139
        assertEq(tickMath.getTickAtSqrtPrice(MAX_SQRT_PRICE - 1), MAX_TICK - 1);
140
    }
141

                            
                        
142
    function test_getTickAtSqrtPrice_isValidMaxSqrtPriceMinusOne() public view {
143
        assertEq(tickMath.getTickAtSqrtPrice(1461373636630004318706518188784493106690254656249), MAX_TICK - 1);
144
    }
145

                            
                        
146
    function test_getSqrtPriceAtTick_matchesJavaScriptImplByOneHundrethOfABip() public {
147
        string memory jsParameters = "";
148

                            
                        
149
        int24 tick = 50;
150

                            
                        
151
        while (true) {
152
            if (tick > MAX_TICK) break;
153
            // test negative and positive tick
154
            for (uint256 i = 0; i < 2; i++) {
155
                tick = tick * -1;
156
                if (tick != -50) jsParameters = string(abi.encodePacked(jsParameters, ",")); // do not leave comma in front of first number
157
                // add tick to javascript parameters to be calculated inside script
158
                jsParameters = string(abi.encodePacked(jsParameters, vm.toString(int256(tick))));
159
                // track solidity result for tick
160
                getSqrtPriceAtTickFuzzResults.push(tickMath.getSqrtPriceAtTick(tick));
161
            }
162
            tick = tick * 2;
163
        }
164

                            
                        
165
        bytes memory jsResult = runScript("forge-test-getSqrtPriceAtTick", jsParameters);
166
        uint160[] memory jsSqrtPrices = abi.decode(jsResult, (uint160[]));
167

                            
                        
168
        for (uint256 i = 0; i < jsSqrtPrices.length; i++) {
169
            uint160 jsSqrtPrice = jsSqrtPrices[i];
170
            uint160 solResult = getSqrtPriceAtTickFuzzResults[i];
171
            (uint160 gtResult, uint160 ltResult) =
172
                jsSqrtPrice > solResult ? (jsSqrtPrice, solResult) : (solResult, jsSqrtPrice);
173
            uint160 resultsDiff = gtResult - ltResult;
174

                            
                        
175
            // assert solc/js result is at most off by 1/100th of a bip (aka one pip)
176
            assertEq(resultsDiff * ONE_PIP / jsSqrtPrice, 0);
177
        }
178
    }
179

                            
                        
180
    function test_getTickAtSqrtPrice_matchesJavascriptImplWithin1() public {
181
        string memory jsParameters = "";
182

                            
                        
183
        uint160 sqrtPrice = MIN_SQRT_PRICE;
184
        unchecked {
185
            while (sqrtPrice < sqrtPrice * 16) {
186
                if (sqrtPrice != MIN_SQRT_PRICE) jsParameters = string(abi.encodePacked(jsParameters, ",")); // do not leave comma in front of first number
187
                // add tick to javascript parameters to be calculated inside script
188
                jsParameters = string(abi.encodePacked(jsParameters, vm.toString(sqrtPrice)));
189
                // track solidity result for sqrtPrice
190
                getTickAtSqrtPriceFuzzResults.push(tickMath.getTickAtSqrtPrice(sqrtPrice));
191
                sqrtPrice = sqrtPrice * 16;
192
            }
193
        }
194

                            
                        
195
        bytes memory jsResult = runScript("forge-test-getTickAtSqrtPrice", jsParameters);
196
        int24[] memory jsTicks = abi.decode(jsResult, (int24[]));
197

                            
                        
198
        for (uint256 i = 0; i < jsTicks.length; i++) {
199
            int24 jsTick = jsTicks[i];
200
            int24 solTick = getTickAtSqrtPriceFuzzResults[i];
201

                            
                        
202
            (int24 gtResult, int24 ltResult) = jsTick > solTick ? (jsTick, solTick) : (solTick, jsTick);
203
            int24 resultsDiff = gtResult - ltResult;
204
            assertLt(resultsDiff, 2);
205
        }
206
    }
207

                            
                        
208
    /// @notice Benchmark the gas cost of `getSqrtPriceAtTick`
209
    function test_getSqrtPriceAtTick_gasCost() public {
210
        snapStart("TickMathGetSqrtPriceAtTick");
211
        unchecked {
212
            for (int24 tick = -50; tick < 50;) {
213
                TickMath.getSqrtPriceAtTick(tick++);
214
            }
215
        }
216
        snapEnd();
217
    }
218

                            
                        
219
    /// @notice Benchmark the gas cost of `getTickAtSqrtPrice`
220
    function test_getTickAtSqrtPrice_gasCost() public {
221
        snapStart("TickMathGetTickAtSqrtPrice");
222
        unchecked {
223
            uint160 sqrtPriceX96 = 1 << 33;
224
            for (uint256 i; i++ < 100; sqrtPriceX96 <<= 1) {
225
                TickMath.getTickAtSqrtPrice(sqrtPriceX96);
226
            }
227
        }
228
        snapEnd();
229
    }
230
}
231

                            
                        

Lines covered: 0 / 15 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {UnsafeMath} from "../../src/libraries/UnsafeMath.sol";
6

                            
                        
7
contract UnsafeMathTest is Test {
8
    using UnsafeMath for uint256;
9

                            
                        
10
    uint256 constant Q128 = 2 ** 128;
11
    uint256 constant MAX_UINT256 = type(uint256).max;
12

                            
                        
13
    function test_divRoundingUp_zeroDoesNotRevert(uint256 x) public pure {
14
        x.divRoundingUp(0);
15
    }
16

                            
                        
17
    function test_divRoundingUp_maxInput() public pure {
18
        assertEq(MAX_UINT256.divRoundingUp(MAX_UINT256), 1);
19
    }
20

                            
                        
21
    function test_divRoundingUp_RoundsUp() public pure {
22
        uint256 result = Q128 / 3 + 1;
23
        assertEq(Q128.divRoundingUp(3), result);
24
    }
25

                            
                        
26
    function test_fuzz_divRoundingUp(uint256 x, uint256 y) public pure {
27
        vm.assume(y != 0);
28
        uint256 result = x.divRoundingUp(y);
29
        assertTrue(result == x / y || result == x / y + 1);
30
    }
31

                            
                        
32
    function test_invariant_divRoundingUp(uint256 x, uint256 y) public pure {
33
        vm.assume(y != 0);
34
        uint256 z = x.divRoundingUp(y);
35
        uint256 diff = z - (x / y);
36
        if (x % y == 0) {
37
            assertEq(diff, 0);
38
        } else {
39
            assertEq(diff, 1);
40
        }
41
    }
42
}
43

                            
                        

Lines covered: 0 / 136 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import "forge-std/Base.sol";
5

                            
                        
6
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
7

                            
                        
8
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
9
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
10
import {PoolKey} from "src/types/PoolKey.sol";
11

                            
                        
12
import {Pool} from "src/libraries/Pool.sol";
13
import {StateLibrary} from "src/libraries/StateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
16

                            
                        
17
import {Actions, ActionsRouter} from "src/test/ActionsRouter.sol";
18
import {Deployers} from "test/utils/Deployers.sol";
19
import {PropertiesAsserts} from "test/trailofbits/PropertiesHelper.sol";
20
import {V4StateMachine} from "test/trailofbits/V4StateMachine.sol";
21
import {ShadowAccounting} from "test/trailofbits/ShadowAccounting.sol";
22

                            
                        
23

                            
                        
24
enum ActionCallbacks {
25
    BEFORE_DONATE,
26
    AFTER_DONATE,
27
    BEFORE_INITIALIZE,
28
    AFTER_INITIALIZE,
29
    BEFORE_SWAP,
30
    AFTER_SWAP,
31
    BEFORE_MODIFY_POSITION,
32
    AFTER_MODIFY_POSITION,
33
    BEFORE_TAKE,
34
    AFTER_TAKE,
35
    BEFORE_SETTLE,
36
    AFTER_SETTLE,
37
    BEFORE_SETTLE_NATIVE,
38
    AFTER_SETTLE_NATIVE,
39
    BEFORE_MINT,
40
    AFTER_MINT,
41
    BEFORE_BURN,
42
    AFTER_BURN,
43
    BEFORE_CLEAR,
44
    AFTER_CLEAR,
45
    BEFORE_SYNC,
46
    AFTER_SYNC,
47
    SHORTCUT_SETTLE,
48
    SET_NEW_PROTOCOL_FEE,
49
    COLLECT_PROTOCOL_FEES,
50
    AFTER_TRANSFER_FROM
51
}
52

                            
                        
53

                            
                        
54
contract ActionFuzzBase is V4StateMachine, ShadowAccounting, ScriptBase {
55
    using TransientStateLibrary for IPoolManager;
56
    using PoolIdLibrary for PoolKey;
57

                            
                        
58
    PoolKey[] public DeployedPools;
59
    mapping(PoolId => bool) PoolInitialized;
60
    Currency[] public Currencies;
61

                            
                        
62

                            
                        
63
    // The fuzzer calls add<X> functions to add actions to the sequence with their corresponding parameters.
64
    Actions[] actions;
65
    bytes[] params;
66

                            
                        
67
    // We'll use these to "cache" sequences so we can run through multiple unlock/lock contexts in a single tx.
68
    // This might help sus out issues related to clearing transient storage.
69
    Actions[][] actionSequences;
70
    bytes[][] paramSequences;
71

                            
                        
72
    uint public NUMBER_CURRENCIES = 6;
73

                            
                        
74
    constructor() payable {
75
        Deployers.deployFreshManagerAndRouters();
76
        // Initialize currencies
77
        for (uint i = 0; i < NUMBER_CURRENCIES; i++) {
78
            // we place the native currency at the end of our currencies array to protect the existing corpus.
79
            if (i == NUMBER_CURRENCIES-1) {
80
                Currencies.push(CurrencyLibrary.NATIVE);
81
            } else {
82
                Currency c = deployMintAndApproveCurrency();
83
                Currencies.push(c);
84
            }
85
        }
86
    }
87

                            
                        
88
    function getActionRouter() public view returns (address) {
89
        return address(actionsRouter);
90
    }
91

                            
                        
92
    function getManager() public view returns (address) {
93
        return address(manager);
94
    }
95

                            
                        
96

                            
                        
97
    function runActions() public {
98
        // start running actions from our stored sequences
99
        for(uint i=0; i<actionSequences.length; i++) {
100
            Actions[] memory a = actionSequences[i];
101
            bytes[] memory p = paramSequences[i];
102
            actionsRouter.executeActions(a, p);
103
   
104
            // UNI-E2E-1    
105
            assertEq(OutstandingDeltas, 0, "Outstanding deltas must be zero after the singleton is re-locked.");
106
        }
107

                            
                        
108
        // run whatever's in the current sequence
109
        actionsRouter.executeActions(actions, params);
110

                            
                        
111
        // UNI-E2E-1      
112
        assertEq(OutstandingDeltas, 0, "Outstanding deltas must be zero after the singleton is re-locked.");
113
        _coverageNudge();
114
        delete actions;
115
        delete params;
116
        delete actionSequences;
117
        delete paramSequences;
118
        _clearTransientRemittances();
119
        emit LogString("pool key");
120
        if(DeployedPools.length > 0) {
121
            emit LogBytes("poolId", abi.encode(DeployedPools[0].toId()));
122
        }
123
    }
124

                            
                        
125
    function prepareNewLock() public {
126
        // store the current sequence
127
        actionSequences.push(actions);
128
        paramSequences.push(params);
129
        delete actions;
130
        delete params;
131
    }
132

                            
                        
133

                            
                        
134
    function _coverageNudge() internal {
135
        for(uint i=0; i<actions.length; i++){
136
            if(actions[i] == Actions.SETTLE){
137
                emit LogString("We did a SETTLE and it worked!");
138
            } else if (actions[i] == Actions.SETTLE_NATIVE){
139
                emit LogString("We did a SETTLE_NATIVE and it worked!");    
140
            } else if (actions[i] == Actions.SETTLE_FOR){
141
                emit LogString("We did a SETTLE_FOR and it worked!");    
142
            } else if (actions[i] == Actions.TAKE){
143
                emit LogString("We did a TAKE and it worked!");    
144
            } else if (actions[i] == Actions.SYNC){
145
                emit LogString("We did a SYNC and it worked!");    
146
            } else if (actions[i] == Actions.MINT){
147
                emit LogString("We did a MINT and it worked!");    
148
            } else if (actions[i] == Actions.BURN){
149
                emit LogString("We did a BURN and it worked!");    
150
            } else if (actions[i] == Actions.CLEAR){
151
                emit LogString("We did a CLEAR and it worked!");    
152
            } else if (actions[i] == Actions.TRANSFER_FROM){
153
                emit LogString("We did a TRANSFER_FROM and it worked!");    
154
            } else if (actions[i] == Actions.INITIALIZE){
155
                emit LogString("We did a INITIALIZE and it worked!");    
156
            } else if (actions[i] == Actions.DONATE){
157
                emit LogString("We did a DONATE and it worked!");    
158
            } else if (actions[i] == Actions.MODIFY_POSITION){
159
                emit LogString("We did a MODIFY_POSITION and it worked!");    
160
            } else if (actions[i] == Actions.SWAP){
161
                emit LogString("We did a SWAP and it worked!");    
162
            } else if (actions[i] == Actions.HARNESS_CALLBACK){
163
                emit LogString("We did a HARNESS_CALLBACK and it worked!");    
164
            }
165
        }
166
    }
167

                            
                        
168
    function _encodeHarnessCallback(ActionCallbacks cbType, bytes memory cbParams) internal view returns (bytes memory) {
169
        bytes memory harnessCbParamEncoded = abi.encode(
170
            cbType,
171
            cbParams
172
        );
173
        
174
        return abi.encode(
175
            address(this),
176
            harnessCbParamEncoded
177
        );
178
    }
179

                            
                        
180
    /// @notice While this function calls it a "clamp", we're technically using modulo so our input space is evenly distributed.
181
    function _clampToUsableTicks(int24 minTick, int24 maxTick, PoolKey memory poolKey) internal returns (int24, int24) {
182
        int24 minUsableTick = TickMath.minUsableTick(poolKey.tickSpacing);
183
        int24 maxUsableTick = TickMath.maxUsableTick(poolKey.tickSpacing);
184

                            
                        
185
        emit LogInt256("minUsableTick", minUsableTick);
186
        emit LogInt256("maxUsableTick", maxUsableTick);
187

                            
                        
188
        minTick = int24(clampBetween(minTick, minUsableTick, maxUsableTick));
189
        maxTick = int24(clampBetween(maxTick, minUsableTick, maxUsableTick));
190

                            
                        
191
        if (maxTick < minTick) {
192
            int24 tmp = minTick;
193
            minTick = maxTick;
194
            maxTick = tmp;
195
        }
196

                            
                        
197
        emit LogInt256("minTick", minTick);
198
        emit LogInt256("maxTick", maxTick);
199
        return (minTick, maxTick);
200
    }
201

                            
                        
202
    /// @notice While this function calls it a "clamp", we're technically using modulo so our input space is evenly distributed.
203
    function _clampToValidCurrencies(uint8 currency1I, uint8 currency2I) internal returns (Currency, Currency) {
204
        uint c1 = clampBetween(currency1I, 0, NUMBER_CURRENCIES-1);
205
        uint c2 = clampBetween(currency2I, 0, NUMBER_CURRENCIES-1);
206
        require(c1 != c2);
207

                            
                        
208
        Currency cur1 = Currencies[c1];
209
        Currency cur2 = Currencies[c2];
210
        if (cur1 >= cur2) {
211
            emit LogAddress("address 1", address(Currency.unwrap(cur2)));
212
            emit LogAddress("address 2", address(Currency.unwrap(cur1)));
213
            return (cur2, cur1);
214
        } else {
215
            emit LogAddress("address 1", address(Currency.unwrap(cur1)));
216
            emit LogAddress("address 2", address(Currency.unwrap(cur2)));
217
            return (cur1, cur2);
218
        }
219
    }
220

                            
                        
221
    /// @notice While this function calls it a "clamp", we're technically using modulo so our input space is evenly distributed.
222
    function _clampToValidPool(uint poolIndex) internal returns ( PoolKey memory) {
223
        poolIndex = clampBetween(poolIndex, 0, DeployedPools.length-1);
224
        emit LogUint256("Pool index", poolIndex);
225
        return DeployedPools[poolIndex];
226
    }
227

                            
                        
228

                            
                        
229
    /* Functions we want as an entrypoint for fuzzing, but do not verify properties for. */
230
    function addTransferFrom(uint8 currency1I, uint256 amount, address from, address to) public {
231
        Currency c1 = Currencies[clampBetween(currency1I, 0, NUMBER_CURRENCIES-1)];
232
        bytes memory param = abi.encode(c1, from, to, amount);
233
        actions.push(Actions.TRANSFER_FROM);
234
        params.push(param);
235

                            
                        
236
        bytes memory cbParams = abi.encode(c1, amount, from, to);
237
        actions.push(Actions.HARNESS_CALLBACK);
238
        params.push(_encodeHarnessCallback(ActionCallbacks.AFTER_TRANSFER_FROM, cbParams));
239
    }
240

                            
                        
241
    function _afterTransferFrom(Currency c, uint256 amount, address, address to) internal {
242
        if(c == RemittanceCurrency && to == address(manager)) {
243
            RemittanceAmount += int256(amount);
244
        }
245
    }
246

                            
                        
247
    /// @notice This function is used to verify various properties that should hold at all times while the singleton is unlocked.
248
    /// When fuzzing a new action, only call _verifyGlobalProperties after doing accounting for our copy of currency deltas,
249
    /// liquidity, etc.
250
    /// It may make more sense for this to live in ShadowAccounting.
251
    function _verifyGlobalProperties(address, Currency currency) internal {
252
        // the only actor in the system we owe money to right now is address(actionsRouter).
253
        // if this changes, we need to sum all currency deltas of all actors, not just actionsRouter
254

                            
                        
255
        int256 delta = manager.currencyDelta(address(actionsRouter), currency);
256
        uint256 singletonBalance = currency.balanceOf(address(manager));
257
        emit LogUint256("Global: singleton balance", singletonBalance);
258

                            
                        
259
        uint256 singletonBalanceInclDelta;
260
        if(delta > 0) {
261
            singletonBalanceInclDelta = singletonBalance - uint256(delta);
262
        } else {
263
            singletonBalanceInclDelta = singletonBalance + uint256(-delta);
264
        }
265
        emit LogUint256("Global: singleton balance incl delta", singletonBalanceInclDelta);
266
        emit LogUint256("Global: singleton liquidity", SingletonLiquidity[currency]);
267
        emit LogUint256("Global: singleton lp fees (in fee growth)", SingletonLPFees[currency]);
268
        emit LogInt256("Global: currencyDelta for actor", delta);
269

                            
                        
270
        assertGte(singletonBalanceInclDelta, SingletonLiquidity[currency], "Bug in harness? Probably turn this into a property.");
271
        
272
        if (delta >= 0) {
273
            // UNI-ACTION-1 (weak, no protocol fees)
274
            assertGte(singletonBalance - SingletonLiquidity[currency], uint256(delta), "The amount owed to an actor must always be less than or equal the balance of the singleton.");
275
        }     
276
        uint256 singletonBalanceAfterRelocking = _deltaAdd(singletonBalance, -delta);
277

                            
                        
278
        // This amount represents the amount of currency that would be remaining in the singleton if every LPer withdrew their liquidity and fees.
279
        uint256 balanceAvailableForProtocolFees = singletonBalanceAfterRelocking - SingletonLiquidity[currency] - SingletonLPFees[currency];
280
        uint256 protocolFees = manager.protocolFeesAccrued(currency);
281
        
282
        // UNI-ACTION-3 
283
        assertLte(protocolFees, balanceAvailableForProtocolFees, "The amount of protocol fees owed may not exceed the singleton's balance (less its deployed liquidity) while the currency has a positive or zero delta.");
284

                            
                        
285
        if (delta >= 0) {
286
            uint256 balanceAvailableForCreditors = singletonBalance - protocolFees - SingletonLiquidity[currency]- SingletonLPFees[currency];
287
            // UNI-ACTION-2 
288
            assertLte(delta, int256(balanceAvailableForCreditors), "The amount owed to an actor must always be less than or equal the balance of the singleton, less protocol fees and LP fees.");
289
        }
290
    }
291

                            
                        
292
    function _deltaAdd(uint256 a, int256 delta) internal returns (uint256 sum)  {
293
        unchecked {
294
            if(delta >= 0){
295
                sum = a + uint256(delta);
296
                assertGte(sum, a, "Sum overflow. This may be a bug in the harness, or an issue in v4.");
297
            } else {
298
                sum = a - uint256(-delta);
299
                assertLt(sum, a, "Sum underflow. This may be a bug in the harness, or an issue in v4.");
300
            }
301
        }
302
    }
303

                            
                        
304
    fallback() external payable {}
305
}

Lines covered: 142 / 170 (83.5%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {IHooks} from "src/interfaces/IHooks.sol";
5
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
6
import {Hooks} from "src/libraries/Hooks.sol";
7
import {TickMath} from "src/libraries/TickMath.sol";
8
import {Position} from "src/libraries/Position.sol";
9
import {Deployers} from "test/utils/Deployers.sol";
10
import {StateLibrary} from "src/libraries/StateLibrary.sol";
11
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
12
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
13
import {PoolKey} from "src/types/PoolKey.sol";
14
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
15
import {PropertiesAsserts} from "./PropertiesHelper.sol";
16
import {IProtocolFeeController} from "src/interfaces/IProtocolFeeController.sol";
17
import {Actions} from "../../src/test/ActionsRouter.sol";
18
import {IActionsHarness} from "./IActionsHarness.sol";
19
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
20
import {ActionFuzzBase, ActionCallbacks} from "./ActionFuzzBase.sol";
21

                            
                        
22

                            
                        
23

                            
                        
24
import {DonateActionProps} from "./actionprops/DonateActionProps.sol";
25
import {InitializeActionProps} from "./actionprops/InitializeActionProps.sol";
26
import {ModifyPositionActionProps} from "./actionprops/ModifyPositionActionProps.sol";
27
import {SwapActionProps} from "./actionprops/SwapActionProps.sol";
28
import {TakeActionProps} from "./actionprops/TakeActionProps.sol";
29
import {SettleActionProps} from "./actionprops/SettleActionProps.sol";
30
import {SettleNativeActionProps} from "./actionprops/SettleNativeActionProps.sol";
31
import {MintActionProps} from "./actionprops/MintActionProps.sol";
32
import {BurnActionProps} from "./actionprops/BurnActionProps.sol";
33
import {SyncActionProps} from "./actionprops/SyncActionProps.sol";
34
import {ClearActionProps} from "./actionprops/ClearActionProps.sol";
35
import {ProtocolFeeActionProps} from "./actionprops/ProtocolFeeActionProps.sol";
36

                            
                        
37
√ 200
contract ActionFuzzEntrypoint is 
38
    ActionFuzzBase, 
39
    IActionsHarness, 
40
    DonateActionProps, 
41
    InitializeActionProps, 
42
    ModifyPositionActionProps,
43
    SwapActionProps,
44
    TakeActionProps,
45
    SettleActionProps,
46
    SettleNativeActionProps,
47
    MintActionProps,
48
    BurnActionProps,
49
    SyncActionProps,
50
    ClearActionProps,
51
    ProtocolFeeActionProps {
52
    using PoolIdLibrary for PoolKey;
53
    using CurrencyLibrary for Currency;
54
    using TransientStateLibrary for IPoolManager;
55

                            
                        
56
    // configure harness in ActionFuzzBase.sol
57
    constructor() payable { }
58

                            
                        
59
    function routerCallback(bytes memory data, bytes memory lastReturnData) external override {
60
√ 3
⟳ 3
        (ActionCallbacks cbType, bytes memory cbData) = abi.decode(data, (ActionCallbacks, bytes));
61

                            
                        
62
√ 2
⟳ 2
        if( cbType == ActionCallbacks.BEFORE_DONATE) {
63
√ 13
⟳ 13
            emit LogString("before donate");
64
√ 2
⟳ 2
            _beforeDonate(cbData);
65
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_DONATE) {
66
√ 13
⟳ 13
            emit LogString("after donate");
67
√ 2
⟳ 2
            BalanceDelta bd = abi.decode(lastReturnData, (BalanceDelta));
68
√ 2
⟳ 2
            _afterDonate(bd);
69
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_SWAP) {
70
√ 13
⟳ 13
            emit LogString("before swap");
71
√ 2
⟳ 2
            _beforeSwap(cbData);
72
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_SWAP) {
73
√ 13
⟳ 13
            emit LogString("after swap");
74
√ 2
⟳ 2
            _afterSwap(abi.decode(lastReturnData, (BalanceDelta)));
75
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_MODIFY_POSITION) {
76
√ 13
⟳ 13
            emit LogString("before modify position");
77
√ 2
⟳ 2
            _beforeModifyPosition(cbData);
78
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_MODIFY_POSITION) {
79
√ 13
⟳ 13
            emit LogString("after modify position");
80
√ 3
⟳ 3
            (BalanceDelta b1, BalanceDelta b2) = abi.decode(lastReturnData, (BalanceDelta,BalanceDelta));
81
√ 3
⟳ 3
            _afterModifyPosition(b1, b2);
82
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_TAKE) {
83
√ 13
⟳ 13
            emit LogString("before take");
84
√ 2
⟳ 2
            _beforeTake(cbData);
85
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_TAKE) {
86
√ 13
⟳ 13
            emit LogString("after take");
87
√ 1
⟳ 1
            _afterTake();
88
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_SETTLE) {
89
√ 13
⟳ 13
            emit LogString("before settle");
90
√ 2
⟳ 2
            _beforeSettle(cbData);
91
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_SETTLE) {
92
√ 13
⟳ 13
            emit LogString("after settle");
93
√ 2
⟳ 2
            uint256 paid = abi.decode(lastReturnData, (uint256));
94
√ 2
⟳ 2
            _afterSettle(paid);
95
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.SHORTCUT_SETTLE) {
96
√ 13
⟳ 13
            emit LogString("shortcut settle");
97
√ 2
⟳ 2
            _shortcutSettle(abi.decode(cbData, (address)));
98
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_SETTLE_NATIVE) {
99
√ 13
⟳ 13
            emit LogString("before settle native");
100
√ 2
⟳ 2
            _beforeSettleNative(cbData);
101
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_SETTLE_NATIVE) {
102
√ 13
⟳ 13
            emit LogString("after settle native");
103
√ 2
⟳ 2
            uint256 paid = abi.decode(lastReturnData, (uint256));
104
√ 2
⟳ 2
            _afterSettleNative(paid);
105
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_MINT) {
106
√ 13
⟳ 13
            emit LogString("before mint");
107
√ 2
⟳ 2
            _beforeMint(cbData);
108
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_MINT) {
109
√ 13
⟳ 13
            emit LogString("after mint");
110
√ 1
⟳ 1
            _afterMint();
111
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_BURN) {
112
√ 13
⟳ 13
            emit LogString("before burn");
113
√ 2
⟳ 2
            _beforeBurn(cbData);
114
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_BURN) {
115
√ 13
⟳ 13
            emit LogString("after burn");
116
√ 1
⟳ 1
            _afterBurn();
117
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_SYNC) {
118
√ 13
⟳ 13
            emit LogString("before sync");
119
√ 2
⟳ 2
            _beforeSync(cbData);
120
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_SYNC) {
121
√ 13
⟳ 13
            emit LogString("after sync");
122
√ 1
⟳ 1
            _afterSync();
123
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.BEFORE_CLEAR) {
124
√ 13
⟳ 13
            emit LogString("before clear");
125
√ 2
⟳ 2
            _beforeClear(cbData);
126
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_CLEAR) {
127
√ 13
⟳ 13
            emit LogString("after clear");
128
√ 1
⟳ 1
            _afterClear();
129
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.SET_NEW_PROTOCOL_FEE) {
130
√ 13
⟳ 13
            emit LogString("set new protocol fee");
131
√ 2
⟳ 2
            _setNewProtocolFee(cbData);
132
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.COLLECT_PROTOCOL_FEES) {
133
√ 13
⟳ 13
            emit LogString("collect protocol fees");
134
√ 2
⟳ 2
            _collectProtocolFees(cbData);
135
√ 2
⟳ 2
        } else if (cbType == ActionCallbacks.AFTER_TRANSFER_FROM) {
136
√ 5
⟳ 5
            (Currency c, uint256 amount, address from, address to) = abi.decode(cbData, (Currency, uint256, address, address));
137
√ 13
⟳ 13
            emit LogString("after transfer from");
138
√ 5
⟳ 5
            _afterTransferFrom(c, amount, from, to);
139
        } else {
140
            assertWithMsg(false, "unknown callback action");
141
        }
142
    }
143

                            
                        
144

                            
                        
145
    function updatePoolDynamicLpFee(uint8 poolIdx, uint24 fee) public {
146
⟳ 3
        PoolKey memory poolKey = _clampToValidPool(poolIdx);
147
⟳ 7
        manager.updateDynamicLPFee(poolKey, fee);
148
        emit LogUint256("modified pool's dynamic fee to ", fee);
149
    }
150

                            
                        
151
    /* The following functions act as "shortcuts" and give the fuzzer a better chance of creating a valid runActions sequence. */
152

                            
                        
153
    /// @notice This function eases coverage generation by adding a new pool and initializing it
154
    function addInitializeAndAddLiquidity(uint8 currency1I, uint8 currency2I, int24 tickSpacing, uint160 startPrice, uint24 fee, int24 minTick, int24 maxTick, int128 liqDelta, uint256 salt) public {
155
√ 6
⟳ 6
        addInitialize(currency1I, currency2I, tickSpacing, startPrice, fee);
156
√ 5
⟳ 5
        uint poolIdx = DeployedPools.length-1;
157
√ 1
⟳ 1
        emit LogUint256("poolidx", poolIdx);
158
√ 6
⟳ 6
        addModifyPosition(uint8(poolIdx), minTick, maxTick, liqDelta, salt);
159
    }
160

                            
                        
161
    /// @notice Doing everything addInitializeAndAddLiquidity does & settle the deltas.
162
    function addInitializeAndAddLiquidityAndSettle(uint8 currency1I, uint8 currency2I, int24 tickSpacing, uint160 startPrice, uint24 fee, int24 minTick, int24 maxTick, int128 liqDelta, uint256 salt) public {
163
√ 10
⟳ 10
        addInitializeAndAddLiquidity(currency1I, currency2I, tickSpacing, startPrice, fee, minTick, maxTick, liqDelta, salt);
164
√ 1
⟳ 1
        runActionsWithShortcutSettle();
165
    }
166

                            
                        
167
    /// @notice Swap into and out of a pair, then settling the deltas.
168
    function addSwapInSwapOut(uint8 poolIdx, bool zeroForOne, int256 amount) public {
169
√ 2
⟳ 2
        if(amount < 0) {
170
√ 2
⟳ 2
            amount = amount * -1;
171
        }
172
        // exact amount out
173
√ 4
⟳ 4
        addSwap(poolIdx, -amount, zeroForOne);
174
        // exact amount in
175
√ 4
        addSwap(poolIdx, amount, !zeroForOne);
176

                            
                        
177
√ 1
        addShortcutSettle();
178
    }
179

                            
                        
180
    /// @notice Creates a pool of highly concentrated liquidity.
181
    function addTargetedPool(uint8 currency1I, uint8 currency2I, uint24 fee, int128 liqDelta) public {
182
√ 2
⟳ 2
        if (liqDelta < 0){
183
√ 1
⟳ 1
            liqDelta = -liqDelta;
184
        }
185
        // concentrate the liquidity on 0,1
186
√ 5
⟳ 5
        try this.addInitializeAndAddLiquidityAndSettle(currency1I, currency2I, 1, 79228162514264337593543950336, fee, 0, 1, liqDelta, 0) {}
187
        catch (bytes memory err) {
188
√ 2
⟳ 2
            bytes4 selector = bytes4(err);
189
√ 5
⟳ 5
            if (selector == Position.CannotUpdateEmptyPosition.selector) {
190
⟳ 3
                assert(false);
191
            }
192
        }
193
    }
194

                            
                        
195
    /// @notice Creates a pool of highly concentrated liquidity with feeGrowthGlobal values that are close to overflowing
196
    function addTargetedPoolReadyToOverflow(uint8 currency1I, uint8 currency2I, uint24 fee) public {
197
√ 5
⟳ 5
        addTargetedPool(currency1I, currency2I, fee, 1);
198
√ 1
⟳ 1
        runActionsWithShortcutSettle();
199
√ 5
⟳ 5
        uint8 poolIdx = uint8(DeployedPools.length-1);
200

                            
                        
201
√ 3
⟳ 3
        addDonate(poolIdx, uint128(type(int128).max), uint128(type(int128).max));
202
√ 1
⟳ 1
        runActionsWithShortcutSettle();
203

                            
                        
204
√ 4
        addDonate(poolIdx, uint128(type(int128).max), uint128(type(int128).max));
205
√ 1
        runActionsWithShortcutSettle();
206
    }
207

                            
                        
208
    /// @notice Performs a donation, then settles and runs the action sequence.
209
    function addDonateAndSettle(uint256 amount0, uint256 amount1) public {
210
√ 5
⟳ 5
        uint8 poolIdx = uint8(DeployedPools.length-1);
211
√ 4
⟳ 4
        addDonate(poolIdx, amount0, amount1);
212
√ 1
⟳ 1
        runActionsWithShortcutSettle();
213
    }
214

                            
                        
215
    /// @notice This custom action is used to automatically settle all of the actor's outstanding deltas.
216
    function addShortcutSettle() public {
217
√ 36
⟳ 27
        address actor = address(actionsRouter);
218

                            
                        
219
√ 100
⟳ 75
        bytes memory shortcutSettleCBParam = abi.encode(address(this), abi.encode(ActionCallbacks.SHORTCUT_SETTLE, abi.encode(actor)));
220
√ 16
⟳ 12
        actions.push(Actions.HARNESS_CALLBACK);
221
        params.push(shortcutSettleCBParam);
222

                            
                        
223
    }
224

                            
                        
225
    /// @notice Settles the actor's outstanding deltas and runs the actions sequence.
226
    function runActionsWithShortcutSettle() public {
227
√ 4
⟳ 3
        addShortcutSettle();
228
√ 4
⟳ 3
        runActions();
229
    }
230

                            
                        
231
    /// @notice Performs a swap, settles the actor's balances, and runs the actions.
232
    function addSwapAndRunActions(uint8 poolIdx, int256 amountSpecified, bool zeroForOne) public {
233
√ 4
⟳ 4
        addSwap(poolIdx, amountSpecified, zeroForOne);
234
√ 1
⟳ 1
	    addShortcutSettle();
235
√ 1
⟳ 1
        runActions();
236
    }
237

                            
                        
238
    /// @notice Performs a burn, settles the actor's balances, and runs the actions.
239
    function addBurnAndRunActions(address from, uint8 curIdx, uint256 amount) public {
240
√ 4
⟳ 4
        addBurn(from, curIdx, amount);
241
 	    addShortcutSettle();
242
        runActions();
243
    } 
244

                            
                        
245
    /// @notice Performs a liquidity modification, settles the actor's balances, and runs the actions.
246
    function addModifyPositionAndRunActions(uint8 poolIdx, int24 lowTick, int24 highTick, int128 liqDelta, uint256 salt) public {
247
√ 6
⟳ 6
        addModifyPosition(poolIdx, lowTick, highTick, liqDelta, salt);
248
√ 1
⟳ 1
  	    addShortcutSettle();
249
√ 1
⟳ 1
        runActions();
250
    } 
251

                            
                        
252
    
253
    function _shortcutSettle(address actor) internal {
254
√ 20
⟳ 17
        for( uint i=0; i<Currencies.length; i++) {
255
√ 18
⟳ 18
            Currency c = Currencies[i];
256
√ 24
⟳ 24
            int256 delta = manager.currencyDelta(actor, c);
257

                            
                        
258
√ 12
⟳ 12
            if(delta < 0) {
259
√ 7
⟳ 14
                manager.sync(c);
260
                
261
                // manually reset remittances
262
                if(!(c == CurrencyLibrary.NATIVE)){
263
√ 1
⟳ 1
                    RemittanceCurrency = c;
264
√ 1
⟳ 1
                    RemittanceAmount = 0;
265
                }
266

                            
                        
267
√ 2
⟳ 4
                uint256 amountOwed = uint256(-delta);
268
                if( c == CurrencyLibrary.NATIVE) {
269
√ 13
⟳ 13
                    emit LogUint256("sending native tokens to manager:", amountOwed);
270
√ 9
⟳ 9
                    manager.settleFor{value: amountOwed}(actor);
271
                } else {
272
√ 13
⟳ 13
                    emit LogUint256("sending tokens to manager:", amountOwed);
273
√ 10
⟳ 10
                    c.transfer( address(manager), amountOwed);
274
√ 7
⟳ 7
                    manager.settleFor(actor);
275
                }
276
√ 13
⟳ 13
                emit LogString("resetting remittance settleForshortcut");
277
√ 1
⟳ 1
                RemittanceCurrency = CurrencyLibrary.NATIVE;
278
√ 1
⟳ 1
                RemittanceAmount = 0;
279
                
280

                            
                        
281
√ 4
⟳ 4
                _addToActorsCredits(actor, c, amountOwed);
282
√ 10
⟳ 8
            } else if (delta > 0) {
283
√ 13
⟳ 13
                emit LogUint256("take tokens:", uint256(delta));
284
√ 4
⟳ 4
                vm.prank(actor);
285
√ 7
⟳ 7
                manager.take(c, address(actor), uint256(delta));
286
√ 4
⟳ 4
                _addToActorsDebts(actor, c, uint256(delta));
287
            }
288
        }
289
    }
290
}

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
interface IActionsHarness {
5
    function routerCallback(bytes memory, bytes memory) external;
6
}

Lines covered: 0 / 225 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.0;
3

                            
                        
4
abstract contract PropertiesAsserts {
5
    event LogUint256(string, uint256);
6
    event LogInt256(string, int256);
7
    event LogAddress(string, address);
8
    event LogString(string);
9
    event LogBytes(string, bytes);
10

                            
                        
11
    event AssertFail(string);
12
    event AssertEqFail(string);
13
    event AssertNeqFail(string);
14
    event AssertGteFail(string);
15
    event AssertGtFail(string);
16
    event AssertLteFail(string);
17
    event AssertLtFail(string);
18

                            
                        
19
    event AssertPassed(string,uint256);
20

                            
                        
21
    string logPrefix;
22

                            
                        
23
    function assertWithMsg(bool b, string memory reason) internal {
24
        if (!b) {
25
            emit AssertFail(reason);
26
            assert(false);
27
        }
28
    }
29

                            
                        
30
    /// @notice asserts that a is equal to b. Violations are logged using reason.
31
    function assertEq(uint256 a, uint256 b, string memory reason) internal {
32
        if (a != b) {
33
            string memory aStr = PropertiesLibString.toString(a);
34
            string memory bStr = PropertiesLibString.toString(b);
35
            bytes memory assertMsg = abi.encodePacked(
36
                "Invalid: ",
37
                aStr,
38
                "!=",
39
                bStr,
40
                ", reason: ",
41
                reason
42
            );
43
            emit AssertEqFail(string(assertMsg));
44
            assert(false);
45
        }
46
    }
47

                            
                        
48
    /// @notice int256 version of assertEq
49
    function assertEq(int256 a, int256 b, string memory reason) internal {
50
        if (a != b) {
51
            string memory aStr = PropertiesLibString.toString(a);
52
            string memory bStr = PropertiesLibString.toString(b);
53
            bytes memory assertMsg = abi.encodePacked(
54
                "Invalid: ",
55
                aStr,
56
                "!=",
57
                bStr,
58
                ", reason: ",
59
                reason
60
            );
61
            emit AssertEqFail(string(assertMsg));
62
            assert(false);
63
        }
64
    }
65

                            
                        
66
    /// @notice asserts that a is not equal to b. Violations are logged using reason.
67
    function assertNeq(uint256 a, uint256 b, string memory reason) internal {
68
        if (a == b) {
69
            string memory aStr = PropertiesLibString.toString(a);
70
            string memory bStr = PropertiesLibString.toString(b);
71
            bytes memory assertMsg = abi.encodePacked(
72
                "Invalid: ",
73
                aStr,
74
                "==",
75
                bStr,
76
                ", reason: ",
77
                reason
78
            );
79
            emit AssertNeqFail(string(assertMsg));
80
            assert(false);
81
        }
82
    }
83

                            
                        
84
    /// @notice int256 version of assertNeq
85
    function assertNeq(int256 a, int256 b, string memory reason) internal {
86
        if (a == b) {
87
            string memory aStr = PropertiesLibString.toString(a);
88
            string memory bStr = PropertiesLibString.toString(b);
89
            bytes memory assertMsg = abi.encodePacked(
90
                "Invalid: ",
91
                aStr,
92
                "==",
93
                bStr,
94
                ", reason: ",
95
                reason
96
            );
97
            emit AssertNeqFail(string(assertMsg));
98
            assert(false);
99
        }
100
    }
101

                            
                        
102
    /// @notice asserts that a is greater than or equal to b. Violations are logged using reason.
103
    function assertGte(uint256 a, uint256 b, string memory reason) internal {
104
        if (!(a >= b)) {
105
            string memory aStr = PropertiesLibString.toString(a);
106
            string memory bStr = PropertiesLibString.toString(b);
107
            bytes memory assertMsg = abi.encodePacked(
108
                "Invalid: ",
109
                aStr,
110
                "<",
111
                bStr,
112
                " failed, reason: ",
113
                reason
114
            );
115
            emit AssertGteFail(string(assertMsg));
116
            assert(false);
117
        } else {
118
            uint256 distance = calcDistance(a,b);
119
            emit AssertPassed(reason, distance);
120
        }
121
    }
122

                            
                        
123
    /// @notice int256 version of assertGte
124
    function assertGte(int256 a, int256 b, string memory reason) internal {
125
        if (!(a >= b)) {
126
            string memory aStr = PropertiesLibString.toString(a);
127
            string memory bStr = PropertiesLibString.toString(b);
128
            bytes memory assertMsg = abi.encodePacked(
129
                "Invalid: ",
130
                aStr,
131
                "<",
132
                bStr,
133
                " failed, reason: ",
134
                reason
135
            );
136
            emit AssertGteFail(string(assertMsg));
137
            assert(false);
138
        } else {
139
            uint256 distance = calcDistance(a,b);
140
            emit AssertPassed(reason, distance);
141
        }
142
    }
143

                            
                        
144

                            
                        
145

                            
                        
146
    /// @notice asserts that a is greater than b. Violations are logged using reason.
147
    function assertGt(uint256 a, uint256 b, string memory reason) internal {
148
        if (!(a > b)) {
149
            string memory aStr = PropertiesLibString.toString(a);
150
            string memory bStr = PropertiesLibString.toString(b);
151
            bytes memory assertMsg = abi.encodePacked(
152
                "Invalid: ",
153
                aStr,
154
                "<=",
155
                bStr,
156
                " failed, reason: ",
157
                reason
158
            );
159
            emit AssertGtFail(string(assertMsg));
160
            assert(false);
161
        } else {
162
            uint256 distance = calcDistance(a,b);
163
            emit AssertPassed(reason, distance-1);
164
        }
165
    }
166

                            
                        
167
    /// @notice int256 version of assertGt
168
    function assertGt(int256 a, int256 b, string memory reason) internal {
169
        if (!(a > b)) {
170
            string memory aStr = PropertiesLibString.toString(a);
171
            string memory bStr = PropertiesLibString.toString(b);
172
            bytes memory assertMsg = abi.encodePacked(
173
                "Invalid: ",
174
                aStr,
175
                "<=",
176
                bStr,
177
                " failed, reason: ",
178
                reason
179
            );
180
            emit AssertGtFail(string(assertMsg));
181
            assert(false);
182
        } else {
183
            uint256 distance = calcDistance(a,b);
184
            emit AssertPassed(reason, distance-1);
185
        }
186
    }
187

                            
                        
188
    /// @notice asserts that a is less than or equal to b. Violations are logged using reason.
189
    function assertLte(uint256 a, uint256 b, string memory reason) internal {
190
        if (!(a <= b)) {
191
            string memory aStr = PropertiesLibString.toString(a);
192
            string memory bStr = PropertiesLibString.toString(b);
193
            bytes memory assertMsg = abi.encodePacked(
194
                "Invalid: ",
195
                aStr,
196
                ">",
197
                bStr,
198
                " failed, reason: ",
199
                reason
200
            );
201
            emit AssertLteFail(string(assertMsg));
202
            assert(false);
203
        } else {
204
            uint256 distance = calcDistance(a,b);
205
            emit AssertPassed(reason, distance);
206
        }
207
    }
208

                            
                        
209
    /// @notice int256 version of assertLte
210
    function assertLte(int256 a, int256 b, string memory reason) internal {
211
        if (!(a <= b)) {
212
            string memory aStr = PropertiesLibString.toString(a);
213
            string memory bStr = PropertiesLibString.toString(b);
214
            bytes memory assertMsg = abi.encodePacked(
215
                "Invalid: ",
216
                aStr,
217
                ">",
218
                bStr,
219
                " failed, reason: ",
220
                reason
221
            );
222
            emit AssertLteFail(string(assertMsg));
223
            assert(false);
224
        } else {
225
            uint256 distance = calcDistance(a,b);
226
            emit AssertPassed(reason, distance);
227
        }
228
    }
229

                            
                        
230
    /// @notice asserts that a is less than b. Violations are logged using reason.
231
    function assertLt(uint256 a, uint256 b, string memory reason) internal {
232
        if (!(a < b)) {
233
            string memory aStr = PropertiesLibString.toString(a);
234
            string memory bStr = PropertiesLibString.toString(b);
235
            bytes memory assertMsg = abi.encodePacked(
236
                "Invalid: ",
237
                aStr,
238
                ">=",
239
                bStr,
240
                " failed, reason: ",
241
                reason
242
            );
243
            emit AssertLtFail(string(assertMsg));
244
            assert(false);
245
        } else {
246
            uint256 distance = calcDistance(a,b);
247
            emit AssertPassed(reason, distance-1);
248
        }
249
    }
250

                            
                        
251
    /// @notice int256 version of assertLt
252
    function assertLt(int256 a, int256 b, string memory reason) internal {
253
        if (!(a < b)) {
254
            string memory aStr = PropertiesLibString.toString(a);
255
            string memory bStr = PropertiesLibString.toString(b);
256
            bytes memory assertMsg = abi.encodePacked(
257
                "Invalid: ",
258
                aStr,
259
                ">=",
260
                bStr,
261
                " failed, reason: ",
262
                reason
263
            );
264
            emit AssertLtFail(string(assertMsg));
265
            assert(false);
266
        } else {
267
            uint256 distance = calcDistance(a,b);
268
            emit AssertPassed(reason, distance);
269
        }
270
    }
271

                            
                        
272
    /// @notice Clamps value to be between low and high, both inclusive
273
    function clampBetween(
274
        uint256 value,
275
        uint256 low,
276
        uint256 high
277
    ) internal returns (uint256) {
278
        if (value < low || value > high) {
279
            uint ans = low + (value % (high - low + 1));
280
            string memory valueStr = PropertiesLibString.toString(value);
281
            string memory ansStr = PropertiesLibString.toString(ans);
282
            bytes memory message = abi.encodePacked(
283
                "Clamping value ",
284
                valueStr,
285
                " to ",
286
                ansStr
287
            );
288
            emit LogString(string(message));
289
            return ans;
290
        }
291
        return value;
292
    }
293

                            
                        
294
    /// @notice int256 version of clampBetween
295
    function clampBetween(
296
        int256 value,
297
        int256 low,
298
        int256 high
299
    ) internal returns (int256) {
300
        if (value < low || value > high) {
301
            int range = high - low + 1;
302
            int clamped = (value - low) % (range);
303
            if (clamped < 0) clamped += range;
304
            int ans = low + clamped;
305
            string memory valueStr = PropertiesLibString.toString(value);
306
            string memory ansStr = PropertiesLibString.toString(ans);
307
            bytes memory message = abi.encodePacked(
308
                "Clamping value ",
309
                valueStr,
310
                " to ",
311
                ansStr
312
            );
313
            emit LogString(string(message));
314
            return ans;
315
        }
316
        return value;
317
    }
318

                            
                        
319
    /// @notice clamps a to be less than b
320
    function clampLt(uint256 a, uint256 b) internal returns (uint256) {
321
        if (!(a < b)) {
322
            assertNeq(
323
                b,
324
                0,
325
                "clampLt cannot clamp value a to be less than zero. Check your inputs/assumptions."
326
            );
327
            uint256 value = a % b;
328
            string memory aStr = PropertiesLibString.toString(a);
329
            string memory valueStr = PropertiesLibString.toString(value);
330
            bytes memory message = abi.encodePacked(
331
                "Clamping value ",
332
                aStr,
333
                " to ",
334
                valueStr
335
            );
336
            emit LogString(string(message));
337
            return value;
338
        }
339
        return a;
340
    }
341

                            
                        
342
    /// @notice int256 version of clampLt
343
    function clampLt(int256 a, int256 b) internal returns (int256) {
344
        if (!(a < b)) {
345
            int256 value = b - 1;
346
            string memory aStr = PropertiesLibString.toString(a);
347
            string memory valueStr = PropertiesLibString.toString(value);
348
            bytes memory message = abi.encodePacked(
349
                "Clamping value ",
350
                aStr,
351
                " to ",
352
                valueStr
353
            );
354
            emit LogString(string(message));
355
            return value;
356
        }
357
        return a;
358
    }
359

                            
                        
360
    /// @notice clamps a to be less than or equal to b
361
    function clampLte(uint256 a, uint256 b) internal returns (uint256) {
362
        if (!(a <= b)) {
363
            uint256 value = a % (b + 1);
364
            string memory aStr = PropertiesLibString.toString(a);
365
            string memory valueStr = PropertiesLibString.toString(value);
366
            bytes memory message = abi.encodePacked(
367
                "Clamping value ",
368
                aStr,
369
                " to ",
370
                valueStr
371
            );
372
            emit LogString(string(message));
373
            return value;
374
        }
375
        return a;
376
    }
377

                            
                        
378
    /// @notice int256 version of clampLte
379
    function clampLte(int256 a, int256 b) internal returns (int256) {
380
        if (!(a <= b)) {
381
            int256 value = b;
382
            string memory aStr = PropertiesLibString.toString(a);
383
            string memory valueStr = PropertiesLibString.toString(value);
384
            bytes memory message = abi.encodePacked(
385
                "Clamping value ",
386
                aStr,
387
                " to ",
388
                valueStr
389
            );
390
            emit LogString(string(message));
391
            return value;
392
        }
393
        return a;
394
    }
395

                            
                        
396
    /// @notice clamps a to be greater than b
397
    function clampGt(uint256 a, uint256 b) internal returns (uint256) {
398
        if (!(a > b)) {
399
            assertNeq(
400
                b,
401
                type(uint256).max,
402
                "clampGt cannot clamp value a to be larger than uint256.max. Check your inputs/assumptions."
403
            );
404
            uint256 value = b + 1;
405
            string memory aStr = PropertiesLibString.toString(a);
406
            string memory valueStr = PropertiesLibString.toString(value);
407
            bytes memory message = abi.encodePacked(
408
                "Clamping value ",
409
                aStr,
410
                " to ",
411
                valueStr
412
            );
413
            emit LogString(string(message));
414
            return value;
415
        } else {
416
            return a;
417
        }
418
    }
419

                            
                        
420
    /// @notice int256 version of clampGt
421
    function clampGt(int256 a, int256 b) internal returns (int256) {
422
        if (!(a > b)) {
423
            int256 value = b + 1;
424
            string memory aStr = PropertiesLibString.toString(a);
425
            string memory valueStr = PropertiesLibString.toString(value);
426
            bytes memory message = abi.encodePacked(
427
                "Clamping value ",
428
                aStr,
429
                " to ",
430
                valueStr
431
            );
432
            emit LogString(string(message));
433
            return value;
434
        } else {
435
            return a;
436
        }
437
    }
438

                            
                        
439
    /// @notice clamps a to be greater than or equal to b
440
    function clampGte(uint256 a, uint256 b) internal returns (uint256) {
441
        if (!(a > b)) {
442
            uint256 value = b;
443
            string memory aStr = PropertiesLibString.toString(a);
444
            string memory valueStr = PropertiesLibString.toString(value);
445
            bytes memory message = abi.encodePacked(
446
                "Clamping value ",
447
                aStr,
448
                " to ",
449
                valueStr
450
            );
451
            emit LogString(string(message));
452
            return value;
453
        }
454
        return a;
455
    }
456

                            
                        
457
    /// @notice int256 version of clampGte
458
    function clampGte(int256 a, int256 b) internal returns (int256) {
459
        if (!(a > b)) {
460
            int256 value = b;
461
            string memory aStr = PropertiesLibString.toString(a);
462
            string memory valueStr = PropertiesLibString.toString(value);
463
            bytes memory message = abi.encodePacked(
464
                "Clamping value ",
465
                aStr,
466
                " to ",
467
                valueStr
468
            );
469
            emit LogString(string(message));
470
            return value;
471
        }
472
        return a;
473
    }
474

                            
                        
475
    /// @notice returns "true" if adding the two unsigned ints would result in an overflow
476
    function doesSumOverflow(uint256 a, uint256 b) internal returns (bool) {
477
        unchecked {
478
            if( a + b < a ){
479
                return true;
480
            } else {
481
                return false;
482
            }
483
        }
484
    }
485

                            
                        
486
    /// @notice returns "true" if adding the two signed ints would result in an overflow
487
    function doesSumOverflow(int256 a, int256 b) internal returns (bool) {
488
        if (a < 0 || b < 0) {
489
            return false;
490
        } else {
491
            return doesSumOverflow(uint256(a), uint256(b));
492
        }
493
    }
494

                            
                        
495
    /// @notice returns "true" if adding the two signed ints would result in an underflow
496
    function doesSumUnderflow(int256 a, int256 b) internal returns (bool) {
497
        if (a > 0 || b > 0) {
498
            return false;
499
        } else {
500
            unchecked {
501
                int256 sum = a + b;
502
                if (sum > a) {
503
                    return true;
504
                } else {
505
                    return false;
506
                }
507
            }
508
        }
509
    }
510

                            
                        
511
    /// @notice returns "true" if adding the two signed ints would result in an overflow or underflow
512
    function doesSumOverUnderflow(int256 a, int256 b) internal returns (bool) {
513
        return doesSumOverflow(a,b) || doesSumUnderflow(a,b);
514
    }
515

                            
                        
516
    /// @notice Calculates the numeric distance between two integers.
517
    function calcDistance(int256 a, int256 b) internal returns (uint256) {
518
        if (b > a) {
519
            int256 tmp = a;
520
            a = b;
521
            b = tmp;
522
        }
523
        uint256 trueDistance;
524
        unchecked {
525
            int256 distance = a - b;
526
            if(distance >= 0) {
527
                trueDistance = uint256(distance);
528
            } else {
529
                a -= type(int256).max;
530
                trueDistance = uint256(a - b) + uint256(type(int256).max);
531
            }
532
        }
533
        return trueDistance;
534
    }
535

                            
                        
536
    /// @notice Calculates the numeric distance between two unsigned integers.
537
    function calcDistance(uint256 a, uint256 b) internal returns (uint256) {
538
        if (b > a) {
539
            uint256 tmp = a;
540
            a = b;
541
            b = tmp;
542
        }
543
        return a - b;
544
    }
545
}
546

                            
                        
547
/// @notice Efficient library for creating string representations of integers.
548
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
549
/// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol)
550
/// @dev Name of the library is modified to prevent collisions with contract-under-test uses of LibString
551
library PropertiesLibString {
552
    function toString(int256 value) internal pure returns (string memory str) {
553
        uint256 absValue = value >= 0 ? uint256(value) : uint256(-value);
554
        str = toString(absValue);
555

                            
                        
556
        if (value < 0) {
557
            str = string(abi.encodePacked("-", str));
558
        }
559
    }
560

                            
                        
561
    function toString(uint256 value) internal pure returns (string memory str) {
562
        /// @solidity memory-safe-assembly
563
        assembly {
564
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes
565
            // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the
566
            // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes.
567
            let newFreeMemoryPointer := add(mload(0x40), 160)
568

                            
                        
569
            // Update the free memory pointer to avoid overriding our string.
570
            mstore(0x40, newFreeMemoryPointer)
571

                            
                        
572
            // Assign str to the end of the zone of newly allocated memory.
573
            str := sub(newFreeMemoryPointer, 32)
574

                            
                        
575
            // Clean the last word of memory it may not be overwritten.
576
            mstore(str, 0)
577

                            
                        
578
            // Cache the end of the memory to calculate the length later.
579
            let end := str
580

                            
                        
581
            // We write the string from rightmost digit to leftmost digit.
582
            // The following is essentially a do-while loop that also handles the zero case.
583
            // prettier-ignore
584
            for { let temp := value } 1 {} {
585
                // Move the pointer 1 byte to the left.
586
                str := sub(str, 1)
587

                            
                        
588
                // Write the character to the pointer.
589
                // The ASCII index of the '0' character is 48.
590
                mstore8(str, add(48, mod(temp, 10)))
591

                            
                        
592
                // Keep dividing temp until zero.
593
                temp := div(temp, 10)
594

                            
                        
595
                 // prettier-ignore
596
                if iszero(temp) { break }
597
            }
598

                            
                        
599
            // Compute and cache the final total length of the string.
600
            let length := sub(end, str)
601

                            
                        
602
            // Move the pointer 32 bytes leftwards to make room for the length.
603
            str := sub(str, 32)
604

                            
                        
605
            // Store the string's length at the start of memory allocated for our string.
606
            mstore(str, length)
607
        }
608
    }
609

                            
                        
610
    function toString(address value) internal pure returns (string memory str) {
611
        bytes memory s = new bytes(40);
612
        for (uint i = 0; i < 20; i++) {
613
            bytes1 b = bytes1(
614
                uint8(uint(uint160(value)) / (2 ** (8 * (19 - i))))
615
            );
616
            bytes1 hi = bytes1(uint8(b) / 16);
617
            bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
618
            s[2 * i] = char(hi);
619
            s[2 * i + 1] = char(lo);
620
        }
621
        return string(s);
622
    }
623

                            
                        
624
    function char(bytes1 b) internal pure returns (bytes1 c) {
625
        if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
626
        else return bytes1(uint8(b) + 0x57);
627
    }
628
}

Lines covered: 0 / 25 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
5

                            
                        
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
8
import {PoolKey} from "src/types/PoolKey.sol";
9

                            
                        
10
import {StateLibrary} from "src/libraries/StateLibrary.sol";
11
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
12

                            
                        
13
import {Deployers} from "test/utils/Deployers.sol";
14

                            
                        
15
import {PropertiesAsserts} from "test/trailofbits/PropertiesHelper.sol";
16

                            
                        
17

                            
                        
18
/// @notice This contract provides a way for the harness to perform "shadow accounting", a technique where
19
/// the harness maintains its own copy of the system's balances, deltas, and remittances. Gas-optimized
20
/// protocols like v4 often need to perform indirect accounting to save gas, but this opens the possibility
21
/// of an error in that indirect accounting that can be exploited, such as an LPer for one pool being able to
22
/// withdraw more tokens than should exist in that pool.
23
/// By maintaining our own, direct copy of the accounting, we can compare it to the results of v4's indirect
24
/// accounting to verify the indirect accounting's correctness.
25
contract ShadowAccounting is PropertiesAsserts, Deployers {
26
    using TransientStateLibrary for IPoolManager;
27

                            
                        
28
    struct PoolBalance {
29
        // While it makes more sense for these to be uint256, it drastically increases the complexity of the casting/math.
30
        // Fix it in the future.
31
        int256 amount0;
32
        int256 amount1;
33
    }
34

                            
                        
35
    // Tracks the tokens available in each pool for trading.
36
    mapping(PoolId => PoolBalance) PoolLiquidities;
37

                            
                        
38
    // Tracks the currency deltas for each actor. 
39
    mapping(address => mapping(Currency => int256)) CurrencyDeltas;
40

                            
                        
41
    // Tracks the liquidity available for swapping within the entire system.
42
    mapping(Currency => uint256) SingletonLiquidity;
43

                            
                        
44
    // Tracks the amount of LP fees available for LPers to withdraw for each currency
45
    mapping(Currency => uint256) SingletonLPFees; 
46

                            
                        
47
    // Our own counter for outstanding deltas, based on CurrencyDeltas.
48
    int256 OutstandingDeltas;
49

                            
                        
50
    // Used to track remittances for settle() properties.
51
    Currency RemittanceCurrency = CurrencyLibrary.NATIVE;
52
    // Any code that transfers currency between the actor and the pool manager should update this.
53
    int256 RemittanceAmount;
54

                            
                        
55
    // This should only be called when we expect transient storage to be cleared, ex: after a transaction terminates.
56
    function _clearTransientRemittances() internal {
57
        RemittanceCurrency = CurrencyLibrary.NATIVE;
58
        RemittanceAmount = 0;
59
    }  
60

                            
                        
61
    function _addToActorsDebts(address actor, Currency currency, uint256 amount) internal {
62
        // UNI-ACTION-4
63
        assertLte(amount, uint256(type(int256).max), "Shadow Accounting: An actor's debited delta must not exceed int256.max for any single action.");
64
        _updateCurrencyDelta(actor, currency, -int256(amount));
65
    }
66

                            
                        
67
    function _addToActorsCredits(address actor, Currency currency, uint256 amount) internal {
68
        // UNI-ACTION-5
69
        assertLte(amount, uint256(type(int256).max), "Shadow Accounting: An actor's credited delta must not exceed int256.max for any single action.");
70
        _updateCurrencyDelta(actor, currency, int256(amount));
71
    }
72
    
73
    function _updateCurrencyDelta(address actor, Currency currency, int256 delta) internal {
74
        int256 prev = CurrencyDeltas[actor][currency];
75
        int256 newD = prev + delta;
76

                            
                        
77
        CurrencyDeltas[actor][currency] = newD;
78
        emit LogAddress("Shadow Accounting: Updating delta for actor", actor);
79
        emit LogAddress("Shadow Accounting: Updating currency being modified", address(Currency.unwrap(currency)));
80

                            
                        
81
        if (prev == 0 && newD != 0) {
82
            // add to array
83
            emit LogAddress("Shadow Accounting: Adding currency to actor's deltas: ", address(Currency.unwrap(currency)));
84
            OutstandingDeltas += 1;
85
        } else if (prev != 0 && newD == 0) {
86
            emit LogString("Shadow Accounting: Removing currency from actor's deltas");
87
            OutstandingDeltas -= 1;
88
        }
89
        emit LogInt256("Shadow Accounting: New delta: ", newD);
90
        emit LogInt256("Shadow Accounting: Prev delta: ", prev);
91
        _sanityCheckCurrencyDelta(actor, currency);
92
    }
93

                            
                        
94
    function _sanityCheckCurrencyDelta(address actor, Currency currency) private {
95
        int256 uniswapCurrencyDelta = manager.currencyDelta(actor, currency);
96
        int256 harnessCurrencyDelta = CurrencyDeltas[actor][currency];
97
        assertEq(uniswapCurrencyDelta, harnessCurrencyDelta, "BUG: Harness currency delta does not match uniswap currency delta");
98
    }
99

                            
                        
100

                            
                        
101
}

Lines covered: 0 / 116 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
5

                            
                        
6
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8

                            
                        
9
import {LiquidityMath} from "src/libraries/LiquidityMath.sol";
10
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
11
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
12
import {Pool} from "src/libraries/Pool.sol";
13
import {SafeCast} from "src/libraries/SafeCast.sol";
14
import {StateLibrary} from "src/libraries/StateLibrary.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {TickBitmap} from "src/libraries/TickBitmap.sol";
17
import {TickMath} from "src/libraries/TickMath.sol";
18
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
19

                            
                        
20
import {Deployers} from "test/utils/Deployers.sol";
21

                            
                        
22
import {PropertiesAsserts} from "test/trailofbits/PropertiesHelper.sol";
23

                            
                        
24
/// @notice This contract contains a limited reproduction of the v4 state machine.
25
/// Context: Some information in the v4 architecture is not directly accessible from any kind of 
26
/// solidity-based getter (example: the amount of LP fees collected for a given swap).
27
/// Since our harness is the only entrypoint for the system, we can cache every single liquidity
28
/// position, then reconstruct the internal tickInfo and tickBitmap for each pool
29
/// immediately before swapping.
30
/// We can then "simulate" the swap against our reconstructed tickInfo/tickBitmap, extracting
31
/// the values we need for verifying properties. 
32
/// In the future, this technique can be extended for modifyLiquidity and be used to verify 
33
/// reversion properties.
34
contract V4StateMachine is PropertiesAsserts, Deployers {
35
    using PoolIdLibrary for PoolKey;
36
    using ProtocolFeeLibrary for *;
37
    using TickBitmap for mapping(int16 => uint256);
38
    using TransientStateLibrary for IPoolManager;
39
    using SafeCast for *;
40
    using StateLibrary for IPoolManager;
41

                            
                        
42
    struct TickInfoUnpacked {
43
        uint128 liquidityGross;
44
        int128 liquidityNet;
45
    }
46

                            
                        
47
    struct TickDescr{
48
        int24 tick;
49
        int24 tickSpacing;
50
    }
51

                            
                        
52
    struct PositionInfo {
53
        uint128 liquidity;
54
        int24 tickLower;
55
        int24 tickUpper;
56
    }
57

                            
                        
58
    // This is used for storing the tickBitmap for all pools. It is deleted and rebuilt before every simulation.
59
    mapping(int16 => uint256) private TickBitmapProxy;
60
    // Used for deleting the TickBitmapProxy mapping
61
    TickDescr[] TickBitmapIndexes;
62

                            
                        
63
    // Used for reconstructing the tickInfo for all pools. It is deleted and rebuilt before every simulation.   
64
    mapping(int24 => TickInfoUnpacked) private TickInfos;
65
    mapping(int24 => bool) private TickInfoInitialized;
66
    // Used for deleting the TickInfos mapping
67
    int24[] private TickInfoIndexes;
68

                            
                        
69
    // a poolId lookup of all positions for the pool.
70
    // Includes positions that are cleared, they simply have 0 liquidity.
71
    // The LiquidityActionProps contract handles adding/updating liquidity positions.
72
    // In the future, consider moving the logic for updating positions into this class to improve decoupling.
73
    mapping(PoolId => PositionInfo[]) PoolPositions;
74

                            
                        
75
    // key is keccak(poolId, positionKey)
76
    // The LiquidityActionProps contract handles adding/updating liquidity positions.
77
    mapping(bytes32 => int) PositionInfoIndex;
78

                            
                        
79
    /// @notice This function is the main entrypoint for the simulated state machine.
80
   function _calculateExpectedLPAndProtocolFees(PoolKey memory pool, bool zeroForOne, int256 amount, uint256 priceLimit) internal returns (uint256, uint256) {
81
        _updateTickBitmapProxy(pool);
82

                            
                        
83
        // Most of following code is a near 1:1 reproduction of Pool.swap()
84
        uint256 feeGrowthGlobalX128;
85
        {
86
            (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = manager.getFeeGrowthGlobals(pool.toId());
87
            feeGrowthGlobalX128 = zeroForOne ? feeGrowthGlobal0X128 : feeGrowthGlobal1X128;
88
        }
89

                            
                        
90
        Pool.SwapState memory state;
91
        uint160 curPrice;
92
        uint24 swapFee;
93
        uint24 protocolFee;
94
        {
95
            int24 curTick;
96
            uint24 protocolFeeRaw;
97
            uint24 lpFee;
98
            (curPrice, curTick, protocolFeeRaw, lpFee) = manager.getSlot0(pool.toId());
99
            state.amountSpecifiedRemaining = amount;
100
            state.amountCalculated = 0;
101
            state.sqrtPriceX96 = curPrice;
102
            state.tick = curTick;
103
            state.feeGrowthGlobalX128 = feeGrowthGlobalX128;
104
            state.liquidity = manager.getLiquidity(pool.toId());
105

                            
                        
106
            if(zeroForOne){
107
                protocolFee = protocolFeeRaw.getZeroForOneFee();
108
            } else {
109
                protocolFee = protocolFeeRaw.getOneForZeroFee();
110
            }
111

                            
                        
112
            if(protocolFee == 0) {
113
                swapFee = lpFee;
114
            } else {
115
                swapFee = uint16(protocolFee).calculateSwapFee(lpFee);
116
            }
117
        }
118

                            
                        
119
        {
120
            bool exactInput = amount < 0;
121
            if((swapFee == LPFeeLibrary.MAX_LP_FEE && !exactInput) || amount == 0) {
122
                return (0,0);
123
            }
124
        }
125

                            
                        
126
        if (zeroForOne) {
127
            if (priceLimit >= curPrice) {
128
                return (0,0);
129
            }
130
            if (priceLimit < TickMath.MIN_SQRT_PRICE) {
131
                return (0,0);
132
            }
133
        } else {
134
            if (priceLimit <= curPrice) {
135
                return (0,0);
136
            }
137
            if (priceLimit >= TickMath.MAX_SQRT_PRICE) {
138
                return (0,0);
139
            }
140
        }
141

                            
                        
142
        // pack into a swapinfo to save stack
143
        Pool.SwapParams memory swapInfo = Pool.SwapParams(
144
            pool.tickSpacing,
145
            zeroForOne,
146
            amount,
147
            uint160(priceLimit),
148
            0
149
        );
150
        return _calculateSteps(swapInfo, state, swapFee, pool.tickSpacing, protocolFee);
151
    }
152

                            
                        
153

                            
                        
154
    /// @notice Continuation of _calculateExpectedLPAndProtocolFees. Needed to save stack space.
155
    function _calculateSteps( Pool.SwapParams memory params, Pool.SwapState memory state, uint24 swapFee, int24 tickSpacing, uint24 protocolFee) private view returns (uint256, uint256) {
156
       Pool.StepComputations memory step;
157
       bool exactInput = params.amountSpecified < 0;
158
       uint256 feeForProtocol;
159
       uint256 feeForLp;
160
       while (!(state.amountSpecifiedRemaining == 0 || state.sqrtPriceX96 == params.sqrtPriceLimitX96)) {
161
            step.sqrtPriceStartX96 = state.sqrtPriceX96;
162

                            
                        
163
            (step.tickNext, step.initialized) =
164
                TickBitmapProxy.nextInitializedTickWithinOneWord(state.tick, tickSpacing, params.zeroForOne);
165

                            
                        
166
            if (step.tickNext <= TickMath.MIN_TICK) {
167
                step.tickNext = TickMath.MIN_TICK;
168
            }
169
            if (step.tickNext >= TickMath.MAX_TICK) {
170
                step.tickNext = TickMath.MAX_TICK;
171
            }
172

                            
                        
173
            step.sqrtPriceNextX96 = TickMath.getSqrtPriceAtTick(step.tickNext);
174

                            
                        
175
            (state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep(
176
                state.sqrtPriceX96,
177
                SwapMath.getSqrtPriceTarget(params.zeroForOne, step.sqrtPriceNextX96, params.sqrtPriceLimitX96),
178
                state.liquidity,
179
                state.amountSpecifiedRemaining,
180
                swapFee
181
            );
182

                            
                        
183
            if (!exactInput) {
184
                unchecked {
185
                    state.amountSpecifiedRemaining -= step.amountOut.toInt256();
186
                }
187
                state.amountCalculated -= (step.amountIn + step.feeAmount).toInt256();
188
            } else {
189
                unchecked {
190
                    state.amountSpecifiedRemaining += (step.amountIn + step.feeAmount).toInt256();
191
                }
192
                state.amountCalculated += step.amountOut.toInt256();
193
            }
194
            if (protocolFee > 0) {
195
                unchecked {
196
                    // step.amountIn does not include the swap fee, as it's already been taken from it,
197
                    // so add it back to get the total amountIn and use that to calculate the amount of fees owed to the protocol
198
                    // this line cannot overflow due to limits on the size of protocolFee and params.amountSpecified
199
                    uint256 delta = (step.amountIn + step.feeAmount) * protocolFee / ProtocolFeeLibrary.PIPS_DENOMINATOR;
200
                    // subtract it from the total fee and add it to the protocol fee
201
                    //emit LogUint256("protocol fee delta", delta);
202
                    step.feeAmount -= delta;
203
                    feeForProtocol += delta;
204
                }
205
            }
206

                            
                        
207
            feeForLp += step.feeAmount;
208
            // skip fee growth calc, don't care
209
            if (state.sqrtPriceX96 == step.sqrtPriceNextX96) {
210
                // if the tick is initialized, run the tick transition
211
                if (step.initialized) {
212

                            
                        
213
                    int128 liquidityNet = TickInfos[step.tickNext].liquidityNet;
214
                    // if we're moving leftward, we interpret liquidityNet as the opposite sign
215
                    // safe because liquidityNet cannot be type(int128).min
216
                    unchecked {
217
                        if (params.zeroForOne) liquidityNet = -liquidityNet;
218
                    }
219
                    state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet);
220
                }
221
                state.tick = params.zeroForOne ? step.tickNext - 1 : step.tickNext;
222
                
223
            } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) {
224
                // recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved
225
                state.tick = TickMath.getTickAtSqrtPrice(state.sqrtPriceX96);
226
            }
227
        }
228

                            
                        
229
        return (protocolFee,feeForLp);
230
    }
231

                            
                        
232
    /// @notice This code reproduces parts of Pool.modifyLiquidity and Pool.updateTick.
233
    /// Some of the logic is rewritten because we don't have to concern ourselves with
234
    /// liquidity removal. Every time this function is called, we're fully reconstructing the state.
235
    function _updateTickBitmapProxy(PoolKey memory pool) private  {
236
        _deleteTickBitmapProxy();
237
        _deleteTickInfos();
238

                            
                        
239
        PositionInfo[] storage positions = PoolPositions[pool.toId()];
240
        for(uint i=0; i<positions.length; i++) {
241
            PositionInfo memory position = positions[i];
242
            if (position.liquidity == 0) {
243
                continue;
244
            }
245
            if( !TickInfoInitialized[position.tickLower]) {
246
                TickInfoIndexes.push(position.tickLower);
247
                TickInfoInitialized[position.tickLower] = true;
248
                TickBitmapProxy.flipTick(position.tickLower, pool.tickSpacing);
249
                TickBitmapIndexes.push(TickDescr(position.tickLower,pool.tickSpacing));
250
                TickInfos[position.tickLower] = TickInfoUnpacked({
251
                    liquidityGross: 0,
252
                    liquidityNet: 0
253
                });
254
            }
255
            
256
            TickInfos[position.tickLower].liquidityGross += position.liquidity;
257
            TickInfos[position.tickLower].liquidityNet =  TickInfos[position.tickLower].liquidityNet + int128(position.liquidity);
258
   
259
            if( !TickInfoInitialized[position.tickUpper]) {
260
                TickInfoIndexes.push(position.tickUpper);
261
                TickInfoInitialized[position.tickUpper] = true;
262
                TickBitmapProxy.flipTick(position.tickUpper, pool.tickSpacing);
263
                TickBitmapIndexes.push(TickDescr(position.tickUpper,pool.tickSpacing));
264
                TickInfos[position.tickUpper] = TickInfoUnpacked({
265
                    liquidityGross: 0,
266
                    liquidityNet: 0
267
                });
268
            }
269
            TickInfos[position.tickUpper].liquidityGross += position.liquidity;
270
            TickInfos[position.tickUpper].liquidityNet =  TickInfos[position.tickUpper].liquidityNet - int128(position.liquidity);
271
        }
272
    }
273

                            
                        
274

                            
                        
275
    function _deleteTickBitmapProxy() private {
276
        for(uint i=0; i<TickBitmapIndexes.length; i++) {
277
            TickDescr memory tickDescr = TickBitmapIndexes[i];
278
            TickBitmapProxy.flipTick(tickDescr.tick, tickDescr.tickSpacing);
279
        }
280
        delete TickBitmapIndexes;
281
    }
282

                            
                        
283
    function _deleteTickInfos() private {
284
        for(uint i=0; i<TickInfoIndexes.length; i++) {
285
            delete TickInfos[TickInfoIndexes[i]];
286
            delete TickInfoInitialized[TickInfoIndexes[i]];
287
        }
288
        delete TickInfoIndexes;
289
    }
290

                            
                        
291
    /// @notice calculate the expected fee growth delta, accounting for overflow.
292
    /// This doesn't actually touch the state machine, but it makes more sense to have it herer than in ActionFuzzBase.
293
    function _calculateExpectedFeeGrowth(uint256 feeGrowthDeltaX128, uint256 prevFeeGrowthX128) internal returns (uint256) {
294
        // we could just do this as unchecked math, but it's nice to verify our assumptions.
295
        uint256 growthOverheadX128 = type(uint256).max - prevFeeGrowthX128;
296
        emit LogUint256("prev fee growth", prevFeeGrowthX128);
297
        emit LogUint256("growth overhead", growthOverheadX128);
298
        emit LogUint256("fee growth delta", feeGrowthDeltaX128);
299
        uint256 feeGrowthExpectedX128;
300
        if( feeGrowthDeltaX128 > growthOverheadX128){
301
            emit LogString("Fee growth is going to overflow");
302
            // overflow case
303
            feeGrowthExpectedX128 = feeGrowthDeltaX128 - growthOverheadX128 - 1;
304
        } else {
305
            emit LogString("Fee growth isn't overflowing");
306
            // normal case
307
            feeGrowthExpectedX128 = prevFeeGrowthX128 + feeGrowthDeltaX128;
308
        }
309
        return feeGrowthExpectedX128;
310
    }
311

                            
                        
312
}

Lines covered: 0 / 27 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
18

                            
                        
19
contract BurnActionProps is ActionFuzzBase {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using StateLibrary for IPoolManager;
23
    using TransientStateLibrary for IPoolManager;
24
    using ProtocolFeeLibrary for uint16;
25

                            
                        
26

                            
                        
27
    address _burnFromActor;
28
    Currency _burnReserveCurrency;
29
    uint256 _burnAmount;
30
    int256 _burnSenderCurrencyDeltaBefore;
31
    uint256 _burnFromActorBalanceBefore;
32

                            
                        
33

                            
                        
34
    function addBurn(address from, uint8 curIdx, uint256 amount) public {
35
        Currency currency = Currencies[clampBetween(curIdx, 0, NUMBER_CURRENCIES-1)];
36

                            
                        
37
        bytes memory burnParams = abi.encode(from, currency, amount);
38
        bytes memory beforeBurnCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_BURN, burnParams);
39

                            
                        
40
        actions.push(Actions.HARNESS_CALLBACK);
41
        params.push(beforeBurnCbParams);
42

                            
                        
43
        actions.push(Actions.BURN);
44
        params.push(burnParams);
45

                            
                        
46
        bytes memory afterBurnCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_BURN, new bytes(0));
47
        actions.push(Actions.HARNESS_CALLBACK);
48
        params.push(afterBurnCbParam);
49
    }
50

                            
                        
51

                            
                        
52
    function _beforeBurn(bytes memory preBurnParams) internal {
53
        (_burnFromActor, _burnReserveCurrency, _burnAmount) = abi.decode(preBurnParams, (address, Currency, uint256));
54
        _burnSenderCurrencyDeltaBefore = manager.currencyDelta(address(actionsRouter), _burnReserveCurrency);
55
        _burnFromActorBalanceBefore = manager.balanceOf(_burnFromActor, _burnReserveCurrency.toId());
56
        emit LogUint256("burn from actor balance", _burnFromActorBalanceBefore);
57
        _verifyGlobalProperties(address(actionsRouter),_burnReserveCurrency);
58
    }
59

                            
                        
60
    function _afterBurn() internal {
61
        int256 senderNewCurrencyDelta = manager.currencyDelta(address(actionsRouter), _burnReserveCurrency);
62
        int256 expectedBurnAmount = senderNewCurrencyDelta - _burnSenderCurrencyDeltaBefore;
63
        
64
        // UNI-SETTLE-4
65
        assertGte(expectedBurnAmount, 0, "After a burn, the sender's currency delta should increase to reflect the decreased debt.");
66
        // UNI-SETTLE-5 (strong version of 4)
67
        assertEq(uint256(expectedBurnAmount), _burnAmount, "After a burn, the difference between the sender's previous and new currency delta should equal the burn amount");
68

                            
                        
69
        uint256 newRecipientBalance = manager.balanceOf(_burnFromActor, _burnReserveCurrency.toId());  
70
        // UNI-SETTLE-6
71
        assertLte(newRecipientBalance, _burnFromActorBalanceBefore, "After a burn, the from actor's balance should decrease to reflect the burned amount");
72

                            
                        
73
        // note: it would be really nice to abstract away some of this overflow checking relationship to reduce the number of meaningless properties.
74
        // property math?
75
        emit LogUint256("new recipient balance", newRecipientBalance);
76
        uint256 fromActorDelta = _burnFromActorBalanceBefore - newRecipientBalance;
77
        // UNI-SETTLE-7
78
        assertEq(fromActorDelta, _burnAmount, "After a burn, the difference between the from actor's previous and new balance should equal the burn amount");
79

                            
                        
80
        _addToActorsCredits(address(actionsRouter), _burnReserveCurrency, _burnAmount);
81
        _verifyGlobalProperties(address(actionsRouter),_burnReserveCurrency);
82
    }      
83

                            
                        
84

                            
                        
85
}

Lines covered: 0 / 20 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
18

                            
                        
19
contract ClearActionProps is ActionFuzzBase {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using StateLibrary for IPoolManager;
23
    using TransientStateLibrary for IPoolManager;
24
    using ProtocolFeeLibrary for uint16;
25

                            
                        
26

                            
                        
27
    Currency _clearCurrency;
28
    uint256 _clearAmount;
29
    int256 _clearActorCurrencyDeltaBefore;
30

                            
                        
31
    function addClear(uint8 curIdx, uint256 amount) public {
32
        Currency currency = Currencies[clampBetween(curIdx, 0, NUMBER_CURRENCIES-1)];
33

                            
                        
34
        bytes memory clearParams = abi.encode(currency, amount, false, "");
35
        bytes memory beforeClearCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_CLEAR, clearParams);
36

                            
                        
37
        actions.push(Actions.HARNESS_CALLBACK);
38
        params.push(beforeClearCbParams);
39

                            
                        
40
        
41
        actions.push(Actions.CLEAR);
42
        params.push(clearParams);
43
        bytes memory afterClearCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_CLEAR, new bytes(0));
44
        actions.push(Actions.HARNESS_CALLBACK);
45
        params.push(afterClearCbParam);
46
    }
47

                            
                        
48

                            
                        
49
    function _beforeClear(bytes memory preClearParams) internal {
50
        (_clearCurrency, _clearAmount,,) = abi.decode(preClearParams, (Currency, uint256, bool, string));
51
        _clearActorCurrencyDeltaBefore = manager.currencyDelta(address(actionsRouter), _clearCurrency);
52

                            
                        
53
        _verifyGlobalProperties(address(actionsRouter),_clearCurrency);
54
    }
55

                            
                        
56
    function _afterClear() internal {
57
        int256 actorCurrencyDeltaAfter = manager.currencyDelta(address(actionsRouter), _clearCurrency);
58

                            
                        
59
        int256 actorCurrencyDelta = _clearActorCurrencyDeltaBefore - actorCurrencyDeltaAfter;
60
        // UNI-SETTLE-12
61
        assertGte(actorCurrencyDelta, 0, "After a clear, the actor's currency delta should go down or be equal to zero.");
62
        // UNI-SETTLE-13
63
        assertEq(uint256(actorCurrencyDelta), _clearAmount, "After a clear, the actor's currency delta should be equal to the amount cleared.");
64

                            
                        
65

                            
                        
66
        _addToActorsDebts(address(actionsRouter), _clearCurrency, _clearAmount);
67
        _verifyGlobalProperties(address(actionsRouter),_clearCurrency);
68
    }      
69

                            
                        
70

                            
                        
71
}
72

                            
                        
73

                            
                        

Lines covered: 0 / 40 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {StateLibrary} from "src/libraries/StateLibrary.sol";
10
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
11
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
12
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {FullMath} from "src/libraries/FullMath.sol";
15

                            
                        
16
contract DonateActionProps is ActionFuzzBase {
17
    using PoolIdLibrary for PoolKey;
18
    using StateLibrary for IPoolManager;
19
    using CurrencyLibrary for Currency;
20
    using TransientStateLibrary for IPoolManager;
21

                            
                        
22
    PoolKey _donatePoolKey;
23
    uint256 _donateAmount0;
24
    uint256 _donateAmount1;
25
    uint256 _feeGrowthGlobal0X128Before;
26
    uint256 _feeGrowthGlobal1X128Before;
27

                            
                        
28
    function addDonate(uint8 poolIdx, uint256 amount0, uint256 amount1) public {
29
        PoolKey memory pk = _clampToValidPool(poolIdx);
30
        bytes memory donateParam = abi.encode(pk, amount0, amount1);
31

                            
                        
32
        actions.push(Actions.HARNESS_CALLBACK);
33
        bytes memory beforeDonateCbParam = _encodeHarnessCallback(ActionCallbacks.BEFORE_DONATE, donateParam);
34
        params.push(beforeDonateCbParam);
35

                            
                        
36
        actions.push(Actions.DONATE);
37
        params.push(donateParam);
38

                            
                        
39
        actions.push(Actions.HARNESS_CALLBACK);
40
        bytes memory afterDonateCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_DONATE, new bytes(0));
41
        params.push(afterDonateCbParam);
42
    }
43

                            
                        
44
    function _beforeDonate(bytes memory preDonateParam) internal {
45
        (_donatePoolKey, _donateAmount0, _donateAmount1) = abi.decode(preDonateParam, (PoolKey, uint256, uint256));
46

                            
                        
47
        (_feeGrowthGlobal0X128Before, _feeGrowthGlobal1X128Before) = manager.getFeeGrowthGlobals(_donatePoolKey.toId());
48
        _verifyGlobalProperties(address(actionsRouter), _donatePoolKey.currency0);
49
        _verifyGlobalProperties(address(actionsRouter), _donatePoolKey.currency1);
50
    }
51

                            
                        
52
    function _afterDonate(BalanceDelta delta) internal {
53
        // UNI-DONATE-6
54
        assertLte(delta.amount0(), 0, "A donate() call must not return a positive BalanceDelta for currency0");
55
        // UNI-DONATE-7
56
        assertLte(delta.amount1(), 0, "A donate() call must not return a positive BalanceDelta for currency1");
57

                            
                        
58
        // UNI-DONATE-8
59
        assertEq(_donateAmount0, uint128(-delta.amount0()), "The donate() call BalanceDelta must match the amount donated for amount0");
60
        // UNI-DONATE-9
61
        assertEq(_donateAmount1, uint128(-delta.amount1()), "The donate() call BalanceDelta must match the amount donated for amount1");
62

                            
                        
63
        PoolId donatePoolId = _donatePoolKey.toId();
64
        uint128 liquidity = manager.getLiquidity(donatePoolId);
65
        
66
        uint256 feeGrowthDelta0X128 = FullMath.mulDiv(uint256(uint128(-delta.amount0())), FixedPoint128.Q128, liquidity);
67
        uint256 feeGrowthDelta1X128 = FullMath.mulDiv(uint256(uint128(-delta.amount1())), FixedPoint128.Q128, liquidity);
68

                            
                        
69
        uint256 feeGrowth0X128Expected = _calculateExpectedFeeGrowth(feeGrowthDelta0X128, _feeGrowthGlobal0X128Before);
70
        uint256 feeGrowth1X128Expected = _calculateExpectedFeeGrowth(feeGrowthDelta1X128, _feeGrowthGlobal1X128Before);
71
        
72

                            
                        
73
        (uint256 feeGrowth0AfterX128, uint256 feeGrowth1AfterX128) = manager.getFeeGrowthGlobals(donatePoolId);
74
        if (liquidity > 0 ) {
75
            if(_donateAmount0 > 0) {
76
                // UNI-DONATE-1
77
                assertEq(feeGrowth0X128Expected, feeGrowth0AfterX128 , "After a donation with a non-zero amount0, the pool's feeGrowthGlobal0X128 be equal to the amount0 BalanceDelta, accounting for overflows.");
78
            } else {
79
                // UNI-DONATE-3
80
                assertEq(_feeGrowthGlobal0X128Before, feeGrowth0AfterX128, "After a donation with a zero amount0, the pool's feeGrowthGlobal0X128 should not change.");
81
            }
82

                            
                        
83
            if(_donateAmount1 > 0) {
84
                // UNI-DONATE-2
85
                assertEq(feeGrowth1X128Expected, feeGrowth1AfterX128, "After a donation with a non-zero amount1, the pool's feeGrowthGlobal0X128 be equal to the amount1 BalanceDelta, accounting for overflows.");
86
            } else {
87
                // UNI-DONATE-4
88
                assertEq(_feeGrowthGlobal1X128Before, feeGrowth1AfterX128, "After a donation with a zero amount1, the pool's feeGrowthGlobal1X128 should not change.");
89
            }
90
        } else {
91
            // fee growth should not have changed
92
            // UNI-DONATE-5
93
            assertWithMsg(false, "Donating to a pool with zero liquidity should result in a revert.");
94
        }
95

                            
                        
96
        /* Update virtual pool reserves  */
97

                            
                        
98
        _updateCurrencyDelta(address(actionsRouter), _donatePoolKey.currency0, delta.amount0());
99
        _updateCurrencyDelta(address(actionsRouter), _donatePoolKey.currency1, delta.amount1());
100

                            
                        
101
        SingletonLPFees[_donatePoolKey.currency0] = _deltaAdd(SingletonLPFees[_donatePoolKey.currency0], int256(_donateAmount0));
102
        SingletonLPFees[_donatePoolKey.currency1] = _deltaAdd(SingletonLPFees[_donatePoolKey.currency1], int256(_donateAmount1));
103

                            
                        
104

                            
                        
105
        _verifyGlobalProperties(address(actionsRouter), _donatePoolKey.currency0);
106
        _verifyGlobalProperties(address(actionsRouter), _donatePoolKey.currency1);
107
    }
108
}

Lines covered: 0 / 54 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {IHooks} from "src/interfaces/IHooks.sol";
10
import {StateLibrary} from "src/libraries/StateLibrary.sol";
11
import {TickMath} from "src/libraries/TickMath.sol";
12
import {Pool} from "src/libraries/Pool.sol";
13
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
14
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
15
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
16

                            
                        
17

                            
                        
18
contract InitializeActionProps is ActionFuzzBase {
19
    using PoolIdLibrary for PoolKey;
20
    using CurrencyLibrary for Currency;
21
    using StateLibrary for IPoolManager;
22

                            
                        
23
    function addInitialize(uint8 currency1I, uint8 currency2I, int24 tickSpacing, uint160 startPrice, uint24 fee) public {
24
        Currency c1;
25
        Currency c2;
26
        (c1, c2) =  _clampToValidCurrencies(currency1I, currency2I);
27
        int24 tickSpacingClamped = int24(clampBetween(tickSpacing,TickMath.MIN_TICK_SPACING, TickMath.MAX_TICK_SPACING));
28
        emit LogInt256("tickSpacingClamped", tickSpacingClamped);
29

                            
                        
30
        uint256 initialPrice = clampBetween(startPrice, TickMath.MIN_SQRT_PRICE, TickMath.MAX_SQRT_PRICE-1);
31
        emit LogUint256("initialPrice", initialPrice);
32
        
33
        uint256 initialFee = clampBetween(fee, 0, ProtocolFeeLibrary.PIPS_DENOMINATOR);
34
        emit LogUint256("initialFee", initialFee);
35

                            
                        
36
        PoolKey memory k = PoolKey(c1, c2, uint24(initialFee), tickSpacingClamped, IHooks(address(0)));
37
        PoolId id = k.toId();
38
        require(!PoolInitialized[id]);
39
        // todo: add revert catcher from e2e harness
40
        try manager.initialize(k, uint160(initialPrice), new bytes(0)) {          
41
        } catch (bytes memory b) {
42
            emit LogBytes("Error", b);
43
            // UNI-INIT-1
44
            assertWithMsg(false, "initialize() should not revert when it is passed valid parameters (tick spacing, price, fee, pool key,  non-existing poo)");
45
        }
46
          
47

                            
                        
48
        DeployedPools.push(k);
49
        PoolInitialized[id] = true;
50
    }
51

                            
                        
52

                            
                        
53
    function addInitializeUnconstrained(uint8 currency1I, uint8 currency2I, int24 tickSpacing, uint160 startPrice, uint24 fee) public {
54
        Currency c1;
55
        Currency c2;
56
        (c1, c2) =  _clampToValidCurrencies(currency1I, currency2I);
57

                            
                        
58
        PoolKey memory k = PoolKey(c1, c2, uint24(fee), tickSpacing, IHooks(address(0)));
59
        PoolId id = k.toId();
60

                            
                        
61
        bool poolinitialized = PoolInitialized[id];
62
        int24 tick;
63

                            
                        
64
        try manager.initialize(k, uint160(startPrice), new bytes(0)) returns (int24 t) {
65
            tick = t;
66
        }  catch (bytes memory data) {
67
            // UNI-INIT-2
68
            if (bytes4(data) == Pool.PoolAlreadyInitialized.selector){
69
                // allowable exception iff poolInitialized
70
                assertWithMsg(poolinitialized, "initialize() must not throw PoolAlreadyInitialized() when there is no pre-existing pool initialized with the same PoolKey");
71
                return;
72
            }
73
            // UNI-INIT-3
74
            if (bytes4(data) == TickMath.InvalidSqrtPrice.selector){
75
                // allowable exception iff initialPrice is outside the valid range
76
                assertWithMsg(startPrice < TickMath.MIN_SQRT_PRICE || startPrice > TickMath.MAX_SQRT_PRICE-1, "initialize() must not throw InvalidSqrtPrice() when provided a price within the valid range");
77
                return;
78
            }
79
            // UNI-INIT-4
80
            if (bytes4(data) == LPFeeLibrary.LPFeeTooLarge.selector){
81
                // allowable exception iff fee is larger than 1_000_000
82
                assertGt(fee, 1_000_000, "initialize() must not throw LPFeeTooLarge() when the fee is in the valid range");
83
                return;
84
            }
85

                            
                        
86
            // UNI-INIT-5
87
            if (bytes4(data) == IPoolManager.TickSpacingTooLarge.selector){
88
                // allowable exception iff tick spacing is >max
89
                assertGt(tickSpacing, TickMath.MAX_TICK_SPACING, "initialize() must not throw TickSpacingTooLarge() when the tick spacing is in the valid range");
90
                return;
91
            }
92

                            
                        
93
            // UNI-INIT-6
94
            if (bytes4(data) == IPoolManager.TickSpacingTooSmall.selector){
95
                // allowable exception iff tick spacing is <min
96
                assertLt(tickSpacing, TickMath.MIN_TICK_SPACING , "initialize() must not throw TickSpacingTooSmall() when the tick spacing is in the valid range");
97
                return;
98
            }
99
            // todo: revisit for other types of errors
100
            require(false);
101
        }
102

                            
                        
103

                            
                        
104
        // UNI-INIT-7
105
        assertWithMsg(!poolinitialized, "initialize() must revert if the provided pool key is already initialized");
106
        // UNI-INIT-8
107
        assertGte(tick, TickMath.MIN_TICK, "initialize() must construct a pool whose tick is greater than or equal to MIN_TICK");
108
        // UNI-INIT-9
109
        assertLte(tick, TickMath.MAX_TICK, "initialize() must construct a pool whose tick is less than or equal to MAX_TICK");
110

                            
                        
111
        (uint160 price, ,,) = manager.getSlot0(id);
112
       // UNI-INIT-10
113
        assertNeq(price, 0, "initialize() must never create a pool with an initial sqrtPrice of zero.");
114

                            
                        
115
        DeployedPools.push(k);
116
        PoolInitialized[id] = true;
117
    }
118

                            
                        
119

                            
                        
120
}

Lines covered: 0 / 28 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
18

                            
                        
19
contract MintActionProps is ActionFuzzBase {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using StateLibrary for IPoolManager;
23
    using TransientStateLibrary for IPoolManager;
24
    using ProtocolFeeLibrary for uint16;
25

                            
                        
26

                            
                        
27
    address _mintRecipient;
28
    Currency _mintReserveCurrency;
29
    uint256 _mintAmount;
30
    int256 _mintSenderCurrencyDeltaBefore;
31
    uint256 _mintRecipientBalanceBefore;
32

                            
                        
33

                            
                        
34
    function addMint(address recipient, uint8 curIdx, uint256 amount) public {
35
        Currency currency = Currencies[clampBetween(curIdx, 0, NUMBER_CURRENCIES-1)];
36

                            
                        
37
        bytes memory mintParams = abi.encode(recipient, currency, amount);
38
        bytes memory beforeMintCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_MINT, mintParams);
39

                            
                        
40
        actions.push(Actions.HARNESS_CALLBACK);
41
        params.push(beforeMintCbParams);
42

                            
                        
43
        actions.push(Actions.MINT);
44
        params.push(mintParams);
45

                            
                        
46
        bytes memory afterMintCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_MINT, new bytes(0));
47
        actions.push(Actions.HARNESS_CALLBACK);
48
        params.push(afterMintCbParam);
49
    }
50

                            
                        
51

                            
                        
52

                            
                        
53
    function _beforeMint(bytes memory preMintParams) internal {
54
        (_mintRecipient, _mintReserveCurrency, _mintAmount) = abi.decode(preMintParams, (address, Currency, uint256));
55
        _mintSenderCurrencyDeltaBefore = manager.currencyDelta(address(actionsRouter), _mintReserveCurrency);
56
        _mintRecipientBalanceBefore = manager.balanceOf(_mintRecipient, _mintReserveCurrency.toId());
57
        _verifyGlobalProperties(address(actionsRouter), _mintReserveCurrency);
58
        emit LogUint256("mint amount", _mintAmount);
59
        emit LogInt256("mint sender currency delta", _mintSenderCurrencyDeltaBefore);
60
    }
61

                            
                        
62
    function _afterMint() internal {
63
        int256 actorCurrencyDeltaAfter = manager.currencyDelta(address(actionsRouter), _mintReserveCurrency);
64
        emit LogInt256("mint sender currency delta after", actorCurrencyDeltaAfter);
65
        int256 expectedDeltaMint = _mintSenderCurrencyDeltaBefore - actorCurrencyDeltaAfter;
66
        // UNI-SETTLE-8
67
        assertGte(expectedDeltaMint, 0, "After a mint, the sender's currency delta should decrease to reflect increased debt.");
68
        // UNI-SETTLE-9
69
        assertEq(uint256(expectedDeltaMint), _mintAmount, "After a mint, the difference between the sender's previous and new currency delta should match the mint amount");
70

                            
                        
71
        uint256 newRecipientBalance = manager.balanceOf(_mintRecipient, _mintReserveCurrency.toId());  
72
        //UNI-SETTLE-10
73
        assertGte(newRecipientBalance, _mintRecipientBalanceBefore, "After a mint, the recipient's ERC6909 balance should increase");
74

                            
                        
75
        uint256 recipientDelta = newRecipientBalance - _mintRecipientBalanceBefore;
76
        // UNI-SETTLE-11
77
        assertEq(recipientDelta, _mintAmount, "After a mint, the recipient's ERC6909 balance should increase by the mint amount");
78

                            
                        
79
        _addToActorsDebts(address(actionsRouter), _mintReserveCurrency, _mintAmount);
80
        _verifyGlobalProperties(address(actionsRouter), _mintReserveCurrency);
81

                            
                        
82
    }      
83

                            
                        
84

                            
                        
85
}

Lines covered: 0 / 101 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {V4StateMachine} from "test/trailofbits/V4StateMachine.sol";
6
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
7
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
8
import {PoolKey} from "src/types/PoolKey.sol";
9
import {Actions} from "src/test/ActionsRouter.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
12
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
13
import {StateLibrary} from "src/libraries/StateLibrary.sol";
14
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
15
import {Position} from "src/libraries/Position.sol";
16
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
17
import {FullMath} from "src/libraries/FullMath.sol";
18

                            
                        
19
contract ModifyPositionActionProps is ActionFuzzBase {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using TransientStateLibrary for IPoolManager;
23
    using StateLibrary for IPoolManager;
24

                            
                        
25
    struct ExistingPosition {
26
        Position.Info positionInfo;
27
    }
28

                            
                        
29
    PoolKey _modifyPoolKey;
30
    bytes32 _modifySalt;
31
    int128 _modifyLiqDelta;
32
    int24 _modifyLowTick;
33
    int24 _modifyHighTick;
34
    uint256 _modifyFeeGrowthGlobal0;
35
    uint256 _modifyFeeGrowthGlobal1;
36

                            
                        
37
    uint128 _modifyPositionLiquidityBefore;
38
    uint256 _modifyFeeGrowthInside0Before;
39
    uint256 _modifyFeeGrowthInside1Before;
40

                            
                        
41
    uint256 _modifyFeesExpectedDelta0X128;
42
    uint256 _modifyFeesExpectedDelta1X128;
43
    uint128 _modifyLiquidityExpected;
44

                            
                        
45
    Position.Info _modifyPositionInfoBefore;
46

                            
                        
47

                            
                        
48

                            
                        
49
    function addModifyPosition(uint8 poolIdx, int24 lowTick, int24 highTick, int128 liqDelta, uint256 salt) public {
50
        // potential props: StateLibrary.getTickLiquidity
51
        // StateLibrary.getLiquidity
52
        // getPositionLiquidity
53

                            
                        
54

                            
                        
55
        // getModifyPositionBefore
56
        // snapshot liquidity of position
57
        // snapshot liquidity of pool
58
        // snapshot fees
59
        // snapshot price
60
        // snapshot tick
61

                            
                        
62

                            
                        
63

                            
                        
64
        // getModifyPositionAfter
65
        
66
        PoolKey memory pk = _clampToValidPool(poolIdx);
67
        
68
        (lowTick, highTick) = _clampToUsableTicks(lowTick, highTick, pk);
69
        bytes memory modifyParam = abi.encode(pk, lowTick, highTick, liqDelta, bytes32(salt));
70

                            
                        
71
        bytes memory beforeModifyCbParam = _encodeHarnessCallback(ActionCallbacks.BEFORE_MODIFY_POSITION, modifyParam);
72
        actions.push(Actions.HARNESS_CALLBACK);
73
        params.push(beforeModifyCbParam);
74

                            
                        
75
        actions.push(Actions.MODIFY_POSITION);
76
        params.push(modifyParam);
77

                            
                        
78
        bytes memory afterModifyCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_MODIFY_POSITION, new bytes(0));
79
        actions.push(Actions.HARNESS_CALLBACK);
80
        params.push(afterModifyCbParam);
81
    }
82

                            
                        
83
    function _beforeModifyPosition(bytes memory preModifyParams) internal {
84
        (_modifyPoolKey, _modifyLowTick, _modifyHighTick,_modifyLiqDelta ,_modifySalt ) =
85
            abi.decode(preModifyParams, (PoolKey, int24, int24, int128, bytes32));
86

                            
                        
87
        (_modifyFeeGrowthGlobal0, _modifyFeeGrowthGlobal1) = manager.getFeeGrowthGlobals(_modifyPoolKey.toId());
88

                            
                        
89
        (_modifyPositionLiquidityBefore, _modifyFeeGrowthInside0Before, _modifyFeeGrowthInside1Before) = manager.getPositionInfo(
90
            _modifyPoolKey.toId(),
91
            _modifySalt
92
        );
93
        _modifyPositionInfoBefore = manager.getPosition(_modifyPoolKey.toId(), address(actionsRouter), _modifyLowTick, _modifyHighTick, _modifySalt);
94
        (_modifyFeesExpectedDelta0X128, _modifyFeesExpectedDelta1X128, _modifyLiquidityExpected) = _calculateExpectedFeeDelta(_modifyPoolKey.toId(), _modifyLiqDelta, _modifyLowTick, _modifyHighTick, address(actionsRouter), _modifySalt);
95

                            
                        
96
        _verifyGlobalProperties(address(actionsRouter), _modifyPoolKey.currency0);
97
        _verifyGlobalProperties(address(actionsRouter), _modifyPoolKey.currency1);
98
        _verifyStateLibraryGetterEquivalence();
99
    }
100

                            
                        
101
    function _afterModifyPosition(BalanceDelta callerDelta, BalanceDelta feesAccrued) internal {
102
        emit LogInt256("modify liquidity callerDelta amount0", callerDelta.amount0());
103
        emit LogInt256("modify liquidity callerDelta amount1", callerDelta.amount1());
104
        emit LogInt256("modify liquidity feesAccrued amount0", feesAccrued.amount0());
105
        emit LogInt256("modify liquidity feesAccrued amount1", feesAccrued.amount1());
106

                            
                        
107
        // UNI-MODLIQ-4
108
        assertGte(feesAccrued.amount0(), 0, "The amount0 of fees accrued from modifyPosition() must be non-negative");
109
        // UNI-MODLIQ-5
110
        assertGte(feesAccrued.amount1(), 0, "The amount1 of fees accrued from modifyPosition() must be non-negative");
111

                            
                        
112

                            
                        
113
        int256 principalDelta0 = callerDelta.amount0() - feesAccrued.amount0();
114
        int256 principalDelta1 = callerDelta.amount1() - feesAccrued.amount1();
115
        emit LogInt256("Change in amount0 principal", principalDelta0);
116
        emit LogInt256("Change in amount1 principal", principalDelta1);
117

                            
                        
118
        // UNI-MODLIQ-8
119
        assertGte(PoolLiquidities[_modifyPoolKey.toId()].amount0, principalDelta0, "The pool must have enough currency0 to return the LP's liquidity balance");
120
        // UNI-MODLIQ-9
121
        assertGte(PoolLiquidities[_modifyPoolKey.toId()].amount1, principalDelta1, "The pool must have enough currency1 to return the LP's liquidity balance");
122

                            
                        
123
        // assert fees == fees expected
124
        assertEq(uint128(feesAccrued.amount0()), _modifyFeesExpectedDelta0X128, "The amount0 of fees accrued from modifyPosition() must match the expected fee.");
125
        assertEq(uint128(feesAccrued.amount1()), _modifyFeesExpectedDelta1X128, "The amount1 of fees accrued from modifyPosition() must match the expected fee.");
126

                            
                        
127
        // UNI-MODLIQ-6
128
        assertGte(SingletonLPFees[_modifyPoolKey.currency0],  uint128(feesAccrued.amount0()), "The singleton must be able to credit the user for the amount of feeGrowth they are owed (amount0)");
129
        // UNI-MODLIQ-7
130
        assertGte(SingletonLPFees[_modifyPoolKey.currency1],  uint128(feesAccrued.amount1()), "The singleton must be able to credit the user for the amount of feeGrowth they are owed (amount1)");
131
        emit LogInt256("hiiisddddi", 5);
132

                            
                        
133
        if(principalDelta0 > 0) {
134
            // UNI-MODLIQ-10
135
            assertGte(SingletonLiquidity[_modifyPoolKey.currency0], uint256(principalDelta0), "The singleton must have enough currency0 to return the LP's liquidity balance");
136
        }
137
        if(principalDelta1 > 0){
138
            // UNI-MOQLIQ-11
139
            assertGte(SingletonLiquidity[_modifyPoolKey.currency1], uint256(principalDelta1), "The singleton must have enough currency1 to return the LP's liquidity balance");
140
        }
141

                            
                        
142
        /* Update virtual pool reserves  */
143
        PoolLiquidities[_modifyPoolKey.toId()].amount0 -= principalDelta0;
144
        PoolLiquidities[_modifyPoolKey.toId()].amount1 -= principalDelta1;
145

                            
                        
146
        emit LogInt256("Pool Liquidity amount0 updated", PoolLiquidities[_modifyPoolKey.toId()].amount0);
147
        emit LogInt256("Pool Liquidity amount1 updated", PoolLiquidities[_modifyPoolKey.toId()].amount1);
148

                            
                        
149
        // Update singleton liquidity
150
        uint256 newSingletonLiq0 = _deltaAdd(SingletonLiquidity[_modifyPoolKey.currency0], -(principalDelta0));
151
        emit LogUint256("Singleton now has this much liquidity for amount0:", newSingletonLiq0);
152
        uint256 newSingletonLiq1 = _deltaAdd(SingletonLiquidity[_modifyPoolKey.currency1], -(principalDelta1));
153
        emit LogUint256("Singleton now has this much liquidity for amount1:", newSingletonLiq1);
154

                            
                        
155
        SingletonLiquidity[_modifyPoolKey.currency0] = newSingletonLiq0;
156
        SingletonLiquidity[_modifyPoolKey.currency1] = newSingletonLiq1;
157

                            
                        
158
        SingletonLPFees[_modifyPoolKey.currency0] -= uint128(feesAccrued.amount0());
159
        SingletonLPFees[_modifyPoolKey.currency1] -= uint128(feesAccrued.amount1());
160

                            
                        
161
        // do not bother using _addToActorsCredits/_addToActorsDebts since BalanceDelta is already int128
162
        _updateCurrencyDelta(address(actionsRouter), _modifyPoolKey.currency0, callerDelta.amount0() );
163
        _updateCurrencyDelta(address(actionsRouter), _modifyPoolKey.currency1, callerDelta.amount1() );
164

                            
                        
165
        // update our positions lookup
166
        _updatePoolPositions();
167

                            
                        
168
        _verifyGlobalProperties(address(actionsRouter), _modifyPoolKey.currency0);
169
        _verifyGlobalProperties(address(actionsRouter), _modifyPoolKey.currency1);
170
    }
171

                            
                        
172
    function _verifyStateLibraryGetterEquivalence() internal {
173
        Position.Info memory positionInfo = manager.getPosition(_modifyPoolKey.toId(), address(actionsRouter), _modifyLowTick, _modifyHighTick, _modifySalt);
174

                            
                        
175
        bytes32 positionId = keccak256(abi.encodePacked(address(actionsRouter), _modifyLowTick, _modifyHighTick, _modifySalt));
176
        (uint128 positionLiq, uint256 positionFeeGrowth0, uint256 positionFeeGrowth1) = manager.getPositionInfo(
177
            _modifyPoolKey.toId(),
178
            positionId
179
        );
180
        // UNI-MODLIQ-1
181
        assertEq(positionInfo.liquidity, positionLiq, "For a specific position, getPositionInfo must return the same liquidity as getPosition");
182
        // UNI-MODLIQ-2
183
        assertEq(positionInfo.feeGrowthInside0LastX128, positionFeeGrowth0, "For a specific position, getPositionInfo must return the same feeGrowthInside0 as getPosition");
184
        // UNI-MODLIQ-3
185
        assertEq(positionInfo.feeGrowthInside1LastX128, positionFeeGrowth1, "For a specific position, getPositionInfo must return the same feeGrowthInside1 as getPosition");
186
    }
187

                            
                        
188
    function _calculateExpectedFeeDelta(PoolId poolId, int128 liqDelta, int24 lowTick, int24 highTick, address owner, bytes32 salt) internal view returns (uint256, uint256,uint128) {
189
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = manager.getFeeGrowthInside(poolId, lowTick, highTick);
190
        Position.Info memory positionInfo = manager.getPosition(poolId, owner, lowTick, highTick, salt);
191

                            
                        
192
        if (liqDelta == 0 && positionInfo.liquidity == 0) {
193
            // this isn't the place for checking properties
194
            return (0,0,0);
195
        }
196
        
197
        // doing this outside yul will let us indirectly check their LiquidityMath.addDelta
198
        uint128 liquidityExpected;
199
        if(liqDelta > 0) {
200
            liquidityExpected = positionInfo.liquidity + uint128(liqDelta);
201
        } else {
202
            liquidityExpected = positionInfo.liquidity - uint128(-liqDelta);
203
        }
204

                            
                        
205
        uint256 feesOwed0;
206
        uint256 feesOwed1;
207

                            
                        
208
        unchecked {
209
            feesOwed0 =
210
                FullMath.mulDiv(feeGrowthInside0X128 - positionInfo.feeGrowthInside0LastX128, positionInfo.liquidity, FixedPoint128.Q128);
211
            feesOwed1 =
212
                FullMath.mulDiv(feeGrowthInside1X128 - positionInfo.feeGrowthInside1LastX128, positionInfo.liquidity, FixedPoint128.Q128);
213
        }
214

                            
                        
215
        return (feesOwed0, feesOwed1, liquidityExpected);
216
    }
217

                            
                        
218
    function _updatePoolPositions() internal {
219
        bytes32 positionId = keccak256(abi.encodePacked(address(actionsRouter), _modifyLowTick, _modifyHighTick, _modifySalt));
220
        (uint128 positionLiq, , ) = manager.getPositionInfo(
221
            _modifyPoolKey.toId(),
222
            positionId
223
        );
224

                            
                        
225
        bytes32 positionInfoLookup = keccak256(abi.encodePacked(_modifyPoolKey.toId(), positionId));
226
        int index = PositionInfoIndex[positionInfoLookup];
227
        if(index == 0) {
228
            // position does not exist in list
229
            V4StateMachine.PositionInfo memory newPosition = V4StateMachine.PositionInfo(0, _modifyLowTick, _modifyHighTick);
230
            index = int(PoolPositions[_modifyPoolKey.toId()].length);
231
            int newPositionIdx = index;
232
            if (newPositionIdx == 0) {
233
                newPositionIdx = -1;
234
            }
235
            PoolPositions[_modifyPoolKey.toId()].push(newPosition);
236
            PositionInfoIndex[positionInfoLookup] = newPositionIdx;
237

                            
                        
238
        } else if (index == -1) {
239
            // we use -1 for the position that actually lives at index 0
240
            index = 0;
241
        }
242
        emit LogInt256("setting liq for position idx", index);
243
        emit LogUint256("to liquidity ", positionLiq);
244

                            
                        
245
        PoolPositions[_modifyPoolKey.toId()][uint(index)].liquidity = positionLiq;
246
    }
247
}

Lines covered: 0 / 29 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {IProtocolFeeController} from "src/interfaces/IProtocolFeeController.sol";
18
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
19

                            
                        
20
contract ProtocolFeeActionProps is ActionFuzzBase {
21
    using PoolIdLibrary for PoolKey;
22
    using CurrencyLibrary for Currency;
23
    using StateLibrary for IPoolManager;
24
    using TransientStateLibrary for IPoolManager;
25
    using ProtocolFeeLibrary for uint16;
26

                            
                        
27

                            
                        
28
    uint24 CurrentProtocolFee;
29

                            
                        
30
    function protocolFeeForPool(PoolKey memory) external view returns (uint24 protocolFee) {
31
        return CurrentProtocolFee;
32
    }
33

                            
                        
34
    /* Setting protocol fee */
35
    function _setNewProtocolFee(bytes memory setNewProtocolFeeParams) internal {
36
        (PoolKey memory poolKey, uint24 amount) = abi.decode(setNewProtocolFeeParams, (PoolKey, uint24));
37

                            
                        
38
        manager.setProtocolFee(poolKey, amount);
39
        CurrentProtocolFee = amount;
40
    }
41

                            
                        
42
    function addSetNewProtocolFee(uint8 poolIdx, uint24 amount) public {
43
        // ensure the protocol fee controller is set first
44
        if(address(manager.protocolFeeController()) != address(this)){
45
            manager.setProtocolFeeController(IProtocolFeeController(address(this)));
46
        }
47
        PoolKey memory poolKey = _clampToValidPool(poolIdx);
48

                            
                        
49
        bytes memory setNewProtocolFeeParams = abi.encode(poolKey, amount);
50
        bytes memory setNewProtocolFeeCbParams = _encodeHarnessCallback(ActionCallbacks.SET_NEW_PROTOCOL_FEE, setNewProtocolFeeParams);
51

                            
                        
52
        actions.push(Actions.HARNESS_CALLBACK);
53
        params.push(setNewProtocolFeeCbParams);
54
 
55
    }
56

                            
                        
57
    /* Collecting protocol fees */
58

                            
                        
59
    function _collectProtocolFees(bytes memory collectProtocolFeesParams) internal {
60
        // we don't need a _before or _after since we're calling this from our harness, not ActionsRouter
61
        Currency currency = abi.decode(collectProtocolFeesParams, (Currency));
62
        uint256 feeToCollect = manager.protocolFeesAccrued(currency);
63

                            
                        
64
        try manager.collectProtocolFees(address(this), currency, feeToCollect) { }
65
        catch(bytes memory b) {
66
            emit LogBytes("error", b);
67
            // UNI-ACTION-6
68
            assertWithMsg(false, "collectProtocolFees must not revert on valid input");
69
        }
70

                            
                        
71
        _verifyGlobalProperties(address(actionsRouter), currency);
72
    }
73

                            
                        
74
    function addCollectProtocolFees(uint8 currencyIdx) public {
75
        Currency currency = Currencies[clampBetween(currencyIdx, 0, NUMBER_CURRENCIES-1)];
76
        if(address(manager.protocolFeeController()) != address(this)){
77
            manager.setProtocolFeeController(IProtocolFeeController(address(this)));
78
        }
79
    
80
        bytes memory collectProtocolFeesParams = abi.encode(currency);
81
        bytes memory collectProtocolFeesCbParams = _encodeHarnessCallback(ActionCallbacks.COLLECT_PROTOCOL_FEES, collectProtocolFeesParams);
82
    
83
        actions.push(Actions.HARNESS_CALLBACK);
84
        params.push(collectProtocolFeesCbParams);
85

                            
                        
86
    }
87
}
88

                            
                        
89

                            
                        

Lines covered: 0 / 32 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
18

                            
                        
19
contract SettleActionProps is ActionFuzzBase {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using StateLibrary for IPoolManager;
23
    using TransientStateLibrary for IPoolManager;
24
    using ProtocolFeeLibrary for uint16;
25

                            
                        
26

                            
                        
27
    address _settleActor;
28
    Currency _settleReserveCurrency;
29
    int256 _currencyDeltaBefore;
30

                            
                        
31

                            
                        
32
    function addSettle() public {
33
        bytes memory beforeSettleCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_SETTLE, abi.encode(address(actionsRouter)));
34

                            
                        
35
        actions.push(Actions.HARNESS_CALLBACK);
36
        params.push(beforeSettleCbParams);
37

                            
                        
38
        actions.push(Actions.SETTLE);
39
        params.push(new bytes(0));
40

                            
                        
41
        bytes memory afterSettleCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SETTLE, new bytes(0));
42
        actions.push(Actions.HARNESS_CALLBACK);
43
        params.push(afterSettleCbParam);
44
    }
45

                            
                        
46
    function addSettleFor(address addr) public {
47
        bytes memory settleForParams = abi.encode(addr);
48

                            
                        
49
        bytes memory beforeSettleCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_SETTLE, settleForParams);
50

                            
                        
51
        actions.push(Actions.HARNESS_CALLBACK);
52
        params.push(beforeSettleCbParams);
53

                            
                        
54
        actions.push(Actions.SETTLE_FOR);
55
        params.push(settleForParams);
56

                            
                        
57
        bytes memory afterSettleCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SETTLE, new bytes(0));
58
        actions.push(Actions.HARNESS_CALLBACK);
59
        params.push(afterSettleCbParam);
60
    }
61

                            
                        
62
    function _beforeSettle(bytes memory preSettleParams) internal {
63
        _settleActor = abi.decode(preSettleParams, (address));     
64
        _settleReserveCurrency = manager.getSyncedCurrency();
65

                            
                        
66
        // The only reason we keep track of remittance currency separately like this is to validate our assumptions about how 
67
        // transient storage works during runtime.
68
        emit LogAddress("synced currency", address(Currency.unwrap(_settleReserveCurrency)));
69
        emit LogAddress("Remittance currency", address(Currency.unwrap(RemittanceCurrency)));
70

                            
                        
71
        _currencyDeltaBefore = manager.currencyDelta(_settleActor, _settleReserveCurrency);
72
        _verifyGlobalProperties(_settleActor, _settleReserveCurrency);
73
    }
74

                            
                        
75
    function _afterSettle(uint256 paid) internal {
76
        int256 currencyDeltaAfterSettle = manager.currencyDelta(_settleActor, _settleReserveCurrency);
77

                            
                        
78
        int256 currencyDeltaDifference = currencyDeltaAfterSettle - _currencyDeltaBefore;
79

                            
                        
80
        // UNI-SETTLE-1
81
        assertGte(currencyDeltaDifference, 0, "The user must not be owed more tokens after a settle than they were owed before a settle.");
82
        // UNI-SETTLE-2
83
        assertEq(currencyDeltaDifference, int256(paid), "The amount paid during a settle must be equal to the difference in the user's currency deltas before and after the settle call.");
84
        // UNI-SETTLE-3
85
        assertEq(int256(paid), RemittanceAmount, "The amount paid during a settle must be equal to the amount of remittances paid to the singleton.");
86

                            
                        
87
        _addToActorsCredits(_settleActor, _settleReserveCurrency, paid);
88
        _verifyGlobalProperties(_settleActor, _settleReserveCurrency);
89
        RemittanceCurrency = CurrencyLibrary.NATIVE;
90
    }      
91

                            
                        
92

                            
                        
93
}
94

                            
                        

Lines covered: 0 / 14 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
18

                            
                        
19
contract SettleNativeActionProps is ActionFuzzBase {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using StateLibrary for IPoolManager;
23
    using TransientStateLibrary for IPoolManager;
24
    using ProtocolFeeLibrary for uint16;
25

                            
                        
26

                            
                        
27
    address _settleNativeActor;
28
    uint256 _settleNativeAmount;
29

                            
                        
30

                            
                        
31
    function addSettleNative(uint256 amount) public {
32

                            
                        
33
        bytes memory beforeSettleCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_SETTLE_NATIVE, abi.encode(address(actionsRouter), amount));
34

                            
                        
35
        actions.push(Actions.HARNESS_CALLBACK);
36
        params.push(beforeSettleCbParams);
37

                            
                        
38
        actions.push(Actions.SETTLE_NATIVE);
39
        params.push(abi.encode(amount));
40

                            
                        
41
        bytes memory afterSettleCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SETTLE_NATIVE, new bytes(0));
42
        actions.push(Actions.HARNESS_CALLBACK);
43
        params.push(afterSettleCbParam);
44
    }
45

                            
                        
46

                            
                        
47
    function _beforeSettleNative(bytes memory preSettleParams) internal {
48
        (_settleNativeActor, _settleNativeAmount) = abi.decode(preSettleParams, (address, uint256));
49
        // transfer currency to actionsRouter
50
        payable(address(actionsRouter)).transfer(_settleNativeAmount);
51

                            
                        
52
        _verifyGlobalProperties(_settleNativeActor, CurrencyLibrary.NATIVE);
53
    }
54

                            
                        
55
    function _afterSettleNative(uint256 paid) internal {
56
        _verifyGlobalProperties(_settleNativeActor, CurrencyLibrary.NATIVE);
57
        _addToActorsCredits(_settleNativeActor, CurrencyLibrary.NATIVE, paid);
58
        
59

                            
                        
60
    }      
61

                            
                        
62

                            
                        
63
}
64

                            
                        
65

                            
                        

Lines covered: 0 / 132 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
18
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
19

                            
                        
20
contract SwapActionProps is ActionFuzzBase {
21
    using PoolIdLibrary for PoolKey;
22
    using CurrencyLibrary for Currency;
23
    using StateLibrary for IPoolManager;
24
    using TransientStateLibrary for IPoolManager;
25
    using ProtocolFeeLibrary for uint16;
26

                            
                        
27
    bool _swapZeroForOne;
28
    int256 _swapAmountSpecified;
29
    PoolKey _swapPoolKey;
30
    uint160 _swapPriceLimit;
31
    int24 _swapTickBefore;
32
    uint24 _swapLpFee;
33
    uint24 _swapProtocolFee;
34
    uint160 _swapSqrtPriceX96Before;
35
    int256 _swapCurrencyDelta0Before;
36
    int256 _swapCurrencyDelta1Before;
37
    uint128 _swapLiquidityBefore;
38
    uint256 _swapFeeGrowthGlobal0X128Before;
39
    uint256 _swapFeeGrowthGlobal1X128Before;
40
    uint256 _swapProtocolFees0;
41
    uint256 _swapProtocolFees1;
42

                            
                        
43
    uint256 _swapExpectedProtocolFee;
44
    uint256 _swapExpectedLpFee;
45

                            
                        
46
    function _addSwap(bool zeroForOne, int256 amountSpecified, PoolKey memory pk, uint160 priceLimit) internal {
47
        bytes memory swapParam = abi.encode(zeroForOne, amountSpecified, pk, priceLimit);
48

                            
                        
49
        bytes memory beforeSwapCbParam = _encodeHarnessCallback(ActionCallbacks.BEFORE_SWAP, swapParam);
50
        actions.push(Actions.HARNESS_CALLBACK);
51
        params.push(beforeSwapCbParam);
52

                            
                        
53
        actions.push(Actions.SWAP);
54
        params.push(swapParam);
55

                            
                        
56
        bytes memory afterSwapCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SWAP, new bytes(0));
57
        actions.push(Actions.HARNESS_CALLBACK);
58
        params.push(afterSwapCbParam);
59
    }
60

                            
                        
61
    function addSwap(uint8 poolIdx, int256 amountSpecified, bool zeroForOne) public {
62
        PoolKey memory pk = _clampToValidPool(poolIdx);
63
        uint160 priceLimit = zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT;
64
        _addSwap(zeroForOne, amountSpecified, pk, priceLimit);
65
    }
66

                            
                        
67
    function _beforeSwap(bytes memory preSwapParam) internal {
68
        (_swapZeroForOne, _swapAmountSpecified, _swapPoolKey, _swapPriceLimit) = abi.decode(preSwapParam, (bool, int256, PoolKey, uint160));
69
        (_swapSqrtPriceX96Before, _swapTickBefore, _swapProtocolFee, _swapLpFee) = manager.getSlot0(_swapPoolKey.toId());
70

                            
                        
71
        _swapCurrencyDelta0Before = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency0);
72
        _swapCurrencyDelta1Before = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency1);
73

                            
                        
74
        emit LogInt256("currency 0 delta before swap", _swapCurrencyDelta0Before);
75
        emit LogInt256("currency 1 delta before swap", _swapCurrencyDelta1Before);
76
        emit LogUint256("sqrt price of pool before swap", _swapSqrtPriceX96Before);
77
        emit LogUint256("sqrt price limit", _swapPriceLimit);
78

                            
                        
79
        _swapLiquidityBefore = manager.getLiquidity(_swapPoolKey.toId());
80
        (_swapFeeGrowthGlobal0X128Before, _swapFeeGrowthGlobal1X128Before) = manager.getFeeGrowthGlobals(_swapPoolKey.toId());
81

                            
                        
82
        _swapProtocolFees0 = manager.protocolFeesAccrued(_swapPoolKey.currency0);
83
        _swapProtocolFees1 = manager.protocolFeesAccrued(_swapPoolKey.currency1);
84
        emit LogUint256("initial protocol fees collected amount0", _swapProtocolFees0);
85
        emit LogUint256("initial protocol fees collected amount1", _swapProtocolFees1);
86

                            
                        
87
        (_swapExpectedProtocolFee, _swapExpectedLpFee) = _calculateExpectedLPAndProtocolFees(_swapPoolKey, _swapZeroForOne, _swapAmountSpecified, _swapPriceLimit);
88

                            
                        
89
        _verifyGlobalProperties(address(actionsRouter), _swapPoolKey.currency0);
90
        _verifyGlobalProperties(address(actionsRouter), _swapPoolKey.currency1);
91
    }
92

                            
                        
93

                            
                        
94

                            
                        
95

                            
                        
96
    function _afterSwap(BalanceDelta delta) internal {
97
        emit LogInt256("amount0 balanceDelta", delta.amount0());
98
        emit LogInt256("amount1 balanceDelta", delta.amount1());
99

                            
                        
100
        /* Properties for the pool's slot0 and how its values have changed */
101
        (uint160 newPrice, int24 newTick,,) = manager.getSlot0(_swapPoolKey.toId());
102
        _verifySlot0Properties(newPrice, newTick);
103
        
104
        /* Fee properties */
105
        _verifyFeeProperties(delta, newTick);
106

                            
                        
107

                            
                        
108
        /* Properties for what we expect has not changed */
109
        uint128 newLiquidity = manager.getLiquidity(_swapPoolKey.toId());
110
        if (newTick == _swapTickBefore) {
111
            // UNI-SWAP-1 (hehe)
112
            assertEq(newLiquidity, _swapLiquidityBefore, "After a swap, if the pool's active tick did not change, its liquidity must be the same as it was before the swap.");
113
        }
114

                            
                        
115
        /* Boundary conditions of swap() */
116
        _verifyBoundaryProperties(newPrice, newTick);
117

                            
                        
118
        /* Verify the key properties of swap() */
119
        _verifySwapBehavior(delta, newPrice, newTick);
120

                            
                        
121
        /* Update our ledger of virtual pool reserves */
122
        _updateSwapBalances(delta);
123

                            
                        
124
        /* These props needs to be verified at the end of the updates */
125
        _verifyGlobalProperties(address(actionsRouter), _swapPoolKey.currency0);
126
        _verifyGlobalProperties(address(actionsRouter), _swapPoolKey.currency1);
127
    }
128

                            
                        
129
    function _verifySlot0Properties(uint160 newPrice, int24 newTick) internal {
130
        emit LogUint256("new pool price", newPrice);
131
        if (_swapZeroForOne) {
132
            // TODO: see if we can get this more restrictive (lte => lt), or even eq
133
            // UNI-SWAP-2
134
            assertLte(newPrice, _swapSqrtPriceX96Before, "The pool's sqrtPriceX96 should decrease or stay the same after making a zeroForOne swap.");
135
            // UNI-SWAP-4
136
            assertGte(newPrice, _swapPriceLimit, "The pool's new sqrtPriceX96 must not be lower than the transaction's price limit after making a zeroForOne swap.");
137
            // UNI-SWAP-6
138
            assertLte(newTick, _swapTickBefore, "The pool's active tick should decrease or stay the same after making a zeroForOne swap.");
139

                            
                        
140
            if (_swapTickBefore - newTick >= 1) {
141
                emit LogString("Successfully crossed multiple ticks in same tx, moving lower");
142
            } else if (_swapTickBefore == newTick) {
143
                emit LogString("Successfully stayed in the same tick while moving lower");
144
            }
145
        } else {
146
            // TODO: see if we can get this more restrictive (gte => gt), or even eq
147
            // UNI-SWAP-3
148
            assertGte(newPrice, _swapSqrtPriceX96Before,  "The pool's sqrtPriceX96 should increase or stay the same after making a oneForZero swap.");
149
            // UNI-SWAP-5
150
            assertLte(newPrice, _swapPriceLimit, "The pool's new sqrtPriceX96 must not exceed the transaction's price limit after making a oneForZero swap.");
151
            // UNI-SWAP-7
152
            assertGte(newTick, _swapTickBefore, "The pool's active tick should increase or stay the same after making a oneForZero swap.");
153

                            
                        
154
            if (newTick - _swapTickBefore >= 1) {
155
                emit LogString("Successfully crossed multiple ticks in same tx, moving higher");
156
            } else if (_swapTickBefore == newTick) {
157
                emit LogString("Successfully stayed in the same tick while moving lower");
158
            }
159
        }
160
    }
161

                            
                        
162
    function _getNumCrossedTicks(int24 oldTick, int24 newTick) internal pure returns (uint256) {
163
        if (oldTick > newTick) {
164
            return uint256(int256(oldTick - newTick));
165
        } else {
166
            return uint256(int256(newTick - oldTick));
167
        }
168
    }
169

                            
                        
170
    function _verifyFeeProperties(BalanceDelta, int24) internal {
171
        /* Properties for how the fees have changed */
172
        (,, uint24 newProtocolFee, uint24 newLpFee) = manager.getSlot0(_swapPoolKey.toId());
173
        (uint256 newSwapFeeGrowth0X128, uint256 newSwapFeeGrowth1X128) = manager.getFeeGrowthGlobals(_swapPoolKey.toId());
174
        
175
        uint256 swapFee = newProtocolFee == 0 ? newLpFee : uint16(newProtocolFee).calculateSwapFee(newLpFee);
176
        emit LogUint256("swap fee", swapFee);
177
        //uint256 numTicksCrossed = _getNumCrossedTicks(newTick, _swapTickBefore);
178

                            
                        
179
        if (_swapZeroForOne) {
180
            // UNI-SWAP-8
181
            assertEq(newSwapFeeGrowth1X128, _swapFeeGrowthGlobal1X128Before, "After a zeroForOne swap, the fee growth for currency1 should not change.");
182

                            
                        
183
            // for now, we can only validate the following props when numTicksCrossed == 0. This is because when multiple ticks are crossed,
184
            // we need to get the liquidity at each tick crossed and figure out how much of the tick was consumed.
185
            // This is totally possible, but has to be saved for future work.
186
            /*
187
            if (true) {
188
                uint256 theoreticalFee = FullMath.mulDivRoundingUp(uint256(int256(-delta.amount0())), swapFee, SwapMath.MAX_FEE_PIPS);
189
                uint256 expectedFeeGrowthDeltaX128 = FullMath.mulDiv(theoreticalFee, FixedPoint128.Q128, _swapLiquidityBefore);
190
                //uint256 expectedFeeGrowth = _calculateExpectedFeeGrowth(expectedFeeGrowthDeltaX128, _swapFeeGrowthGlobal0X128Before);
191
                // UNI-SWAP-10 (remove)
192
                //assertEq(expectedFeeGrowth, newSwapFeeGrowth0X128, "After a zeroForOneSwap, the fee growth for currency0 should match the expected fee growth.");
193
            }
194
            */
195
        } else {
196
            // UNI-SWAP-9
197
            assertEq(newSwapFeeGrowth0X128, _swapFeeGrowthGlobal0X128Before, "After a oneForZero swap, the fee growth for currency0 should not change.");
198
            /*
199
            if (true) {
200
                uint256 theoreticalFee = FullMath.mulDivRoundingUp(uint256(int256(-delta.amount1())), swapFee, SwapMath.MAX_FEE_PIPS);
201
                emit LogUint256("swap liquidity", _swapLiquidityBefore);
202
                uint256 expectedFeeGrowthDeltaX128 = FullMath.mulDiv(theoreticalFee, FixedPoint128.Q128, _swapLiquidityBefore);
203
                emit LogUint256("prev fee growth", _swapFeeGrowthGlobal1X128Before);
204
                emit LogUint256("theoretical fee", theoreticalFee);
205
                emit LogUint256("expectedFeeGrowthDeltaX128", expectedFeeGrowthDeltaX128);
206
                //uint256 expectedFeeGrowth = _calculateExpectedFeeGrowth(expectedFeeGrowthDeltaX128, _swapFeeGrowthGlobal1X128Before);
207
                // UNI-SWAP-11 (remove)
208
                //assertEq(expectedFeeGrowth, newSwapFeeGrowth1X128, "After a oneForZero, the fee growth for currency1 should match the expected fee growth. ");
209
            }
210
            */
211
        } 
212
    }
213

                            
                        
214

                            
                        
215
    function _verifyBoundaryProperties(uint160 newPrice, int24 newTick) internal {
216
        // UNI-SWAP-10
217
        assertNeq(_swapAmountSpecified, 0, "The swap action must revert if swap amount is zero.");
218
        // UNI-SWAP-11
219
        assertLt(newPrice, TickMath.MAX_SQRT_PRICE, "The pool's new price must be less than MAX_SQRT_PRICE");
220
        // UNI-SWAP-12
221
        assertGt(newPrice, TickMath.MIN_SQRT_PRICE, "The pool's new price must be greater than or equal to MIN_SQRT_PRICE");
222
        // UNI-SWAP-13
223
        assertLte(newTick, TickMath.MAX_TICK, "The pool's new tick must be less than or equal to MAX_TICK");
224
        // UNI-SWAP-14
225
        assertGte(newTick, TickMath.MIN_TICK, "The pool's new tick must be greater than or equal to MIN_TICK");
226
    }
227

                            
                        
228
    function _verifySwapBehavior(BalanceDelta delta, uint160 newPrice, int24) internal {
229
        int256 currencyDelta0After = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency0);
230
        int256 currencyDelta1After = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency1);
231

                            
                        
232
        /* Properties of swap()'s behavior */
233
        // We use fromBalanceDelta/toBalanceDelta to reduce the number of properties. There's no need to if(zeroForOne) constantly.
234
        // The assumptions introduced by using this abstraction are checked in SWAP-PROP-17/SWAP-PROP-18.
235
        int128 fromBalanceDelta = _swapZeroForOne ? delta.amount0() : delta.amount1();
236
        int128 toBalanceDelta = _swapZeroForOne ? delta.amount1() : delta.amount0();
237
        int256 fromCurrencyDeltaFull;
238
        int256 toCurrencyDeltaFull;
239
        if (_swapZeroForOne) {
240
            fromCurrencyDeltaFull = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency0);
241
            toCurrencyDeltaFull = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency1);
242
            emit LogString("zeroForOne");
243
        }else {
244
            fromCurrencyDeltaFull = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency1);
245
            toCurrencyDeltaFull = manager.currencyDelta(address(actionsRouter), _swapPoolKey.currency0);
246
            emit LogString("oneforzero");
247
        }
248
        emit LogInt256("fromBalanceDelta", fromBalanceDelta);
249
        emit LogInt256("toBalanceDelta", toBalanceDelta);
250
        emit LogInt256("currencyDelta0After", currencyDelta0After);
251
        emit LogInt256("currencyDelta1After", currencyDelta1After);
252
        emit LogInt256("_swapAmountSpecified", _swapAmountSpecified);
253

                            
                        
254
        if (fromBalanceDelta != 0 && toBalanceDelta != 0){
255
            // UNI-SWAP-15 transitive; Swaps respect the sqrtPriceLimit ahead of the need to consume exactInput or exactOutput.
256
            if(_swapPriceLimit != newPrice){
257
                if (_swapAmountSpecified < 0) {
258
                    // exact input
259
                    // UNI-SWAP-16, iff the price limit was not reached
260
                    assertEq(fromBalanceDelta, _swapAmountSpecified, "For exact input swaps where the price limit is not reached, the fromBalanceDelta must match the exact input amount.");
261
                } else {
262
                    // exact output
263
                    // UNI-SWAP-17, iff the price limit was not reached
264
                    assertEq(toBalanceDelta, _swapAmountSpecified, "For exact output swaps where the price limit is not reached, the toBalanceDelta must match the exact output amount.");
265
                }
266
            } else {
267
                // todo: use lte/gte to ensure price limit was not exceeded
268
            }
269
        } else { 
270
            // One or both of the deltas being zero should be a result of rounding down to zero, but there is still a case we need to check for.
271
            if (fromBalanceDelta == 0) {
272
                // UNI-SWAP-18
273
                assertEq(toBalanceDelta, 0, "If the fromBalanceDelta of a swap is zero, the toBalanceDelta must also be zero (rounding).");
274
            }
275
        }
276

                            
                        
277
        /* Properties of the system's currencyDeltas and how it compares to balanceDelta */
278
        // UNI-SWAP-19
279
        assertGte(toBalanceDelta, 0, "For any swap, the amount credited to the user is greater than or equal to zero.");
280
        // UNI-SWAP-20
281
        assertLte(fromBalanceDelta, 0, "For any swap, the amount credited to the user is less than or equal to zero");
282

                            
                        
283
        int256 expectedDelta0After = _swapCurrencyDelta0Before + delta.amount0();
284
        int256 expectedDelta1After = _swapCurrencyDelta1Before + delta.amount1();
285

                            
                        
286
        // if our deltas are bigger than the liquidity that was in the pool, this action is stealing tokens from another pool.
287
        if(_swapZeroForOne) {
288
            // UNI-SWAP-21 
289
            assertLte(int256(delta.amount1()), PoolLiquidities[_swapPoolKey.toId()].amount1, "For a zeroForOne swap, the amount credited to the user must be less than or equal to the total number of tradeable tokens in the pool");
290
        } else {
291
            // UNI-SWAP-22
292
            assertLte(int256(delta.amount0()), PoolLiquidities[_swapPoolKey.toId()].amount0, "For a oneForZero swap, the amount credited to the user must be less than or equal to the total number of tradeable tokens in the pool");
293
        }
294

                            
                        
295
        // UNI-SWAP-23
296
        assertEq(currencyDelta0After, expectedDelta0After, "After a swap, the user's currencyDelta for amount0 should match the expected delta based on BalanceDelta.");
297
        // UNI-SWAP-24
298
        assertEq(currencyDelta1After, expectedDelta1After, "After a swap, the user's currencyDelta for amount1 should match the expected delta based on BalanceDelta.");      
299
    }
300

                            
                        
301
    function _updateSwapBalances(BalanceDelta delta) internal {
302
        emit LogInt256("cur0 BalanceDelta from swap", delta.amount0());
303
        emit LogInt256("cur1 BalanceDelta from swap", delta.amount1());
304

                            
                        
305
        int256 expectedLpFee0;
306
        int256 expectedLpFee1;
307

                            
                        
308
        if(_swapZeroForOne) {
309
            expectedLpFee0 = int256(_swapExpectedLpFee);
310
            SingletonLPFees[_swapPoolKey.currency0] += _swapExpectedLpFee;
311
            emit LogUint256("new singleton LP fees (amount0)", SingletonLPFees[_swapPoolKey.currency0]);
312
        } else {
313
            expectedLpFee1 = int256(_swapExpectedLpFee);
314
            SingletonLPFees[_swapPoolKey.currency1] += _swapExpectedLpFee;
315
            emit LogUint256("new singleton LP fees (amount1)", SingletonLPFees[_swapPoolKey.currency1]);
316
        }
317

                            
                        
318
        {
319
            uint256 protocolFeesLevied0 = (manager.protocolFeesAccrued(_swapPoolKey.currency0)-(_swapProtocolFees0));
320
            uint256 protocolFeesLevied1 = (manager.protocolFeesAccrued(_swapPoolKey.currency1)-(_swapProtocolFees1));
321

                            
                        
322
            emit LogUint256("protocol fees levied amount0", protocolFeesLevied0);
323
            emit LogUint256("protocol fees levied amount1", protocolFeesLevied1);
324

                            
                        
325
            emit LogInt256("prev pool liquidity amount0", PoolLiquidities[_swapPoolKey.toId()].amount0);
326
            emit LogInt256("prev pool liquidity amount1", PoolLiquidities[_swapPoolKey.toId()].amount1);
327
            
328
            PoolLiquidities[_swapPoolKey.toId()].amount0 -= delta.amount0() + int256(protocolFeesLevied0) + expectedLpFee0;
329
            PoolLiquidities[_swapPoolKey.toId()].amount1 -= delta.amount1() + int256(protocolFeesLevied1) + expectedLpFee1;
330
            emit LogInt256("new pool liquidity amount0", PoolLiquidities[_swapPoolKey.toId()].amount0);
331
            emit LogInt256("new pool liquidity amount1", PoolLiquidities[_swapPoolKey.toId()].amount1);
332

                            
                        
333
            // Update singleton liquidity, remove the amount sent/recvd from user.
334
            uint256 newSingletonLiq0 = _deltaAdd(SingletonLiquidity[_swapPoolKey.currency0], -(delta.amount0()));
335
            uint256 newSingletonLiq1 = _deltaAdd(SingletonLiquidity[_swapPoolKey.currency1], -(delta.amount1()));
336

                            
                        
337
            // Update singleton liquidity, remove the amount consumed by protocol.
338
            newSingletonLiq0 = _deltaAdd(newSingletonLiq0, -int256(protocolFeesLevied0));
339
            newSingletonLiq1 = _deltaAdd(newSingletonLiq1, -int256(protocolFeesLevied1));
340

                            
                        
341
            newSingletonLiq0 = _deltaAdd(newSingletonLiq0, -int256(expectedLpFee0));
342
            newSingletonLiq1 = _deltaAdd(newSingletonLiq1, -int256(expectedLpFee1));
343

                            
                        
344
            SingletonLiquidity[_swapPoolKey.currency0] = newSingletonLiq0;
345
            SingletonLiquidity[_swapPoolKey.currency1] = newSingletonLiq1;
346

                            
                        
347
            _updateCurrencyDelta(address(actionsRouter), _swapPoolKey.currency0, delta.amount0());
348
            _updateCurrencyDelta(address(actionsRouter), _swapPoolKey.currency1, delta.amount1());
349
        }
350

                            
                        
351
    }
352

                            
                        
353

                            
                        
354
}

Lines covered: 0 / 15 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
18

                            
                        
19
contract SyncActionProps is ActionFuzzBase {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using StateLibrary for IPoolManager;
23
    using TransientStateLibrary for IPoolManager;
24
    using ProtocolFeeLibrary for uint16;
25

                            
                        
26
    Currency _syncCurrency;
27

                            
                        
28
    function addSync(uint8 curIdx) public {
29
        Currency currency = Currencies[clampBetween(curIdx, 0, NUMBER_CURRENCIES-1)];
30

                            
                        
31

                            
                        
32
        bytes memory syncParams = abi.encode(currency);
33
        bytes memory beforeSyncCbParams = _encodeHarnessCallback(ActionCallbacks.BEFORE_SYNC, syncParams);
34

                            
                        
35
        actions.push(Actions.HARNESS_CALLBACK);
36
        params.push(beforeSyncCbParams);
37

                            
                        
38
        actions.push(Actions.SYNC);
39
        params.push(syncParams);
40

                            
                        
41
        bytes memory afterSyncCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_SYNC, new bytes(0));
42
        actions.push(Actions.HARNESS_CALLBACK);
43
        params.push(afterSyncCbParam);
44
    }
45

                            
                        
46
    function _beforeSync(bytes memory preSyncParams) internal {
47
        _syncCurrency = abi.decode(preSyncParams, (Currency));
48
    }
49

                            
                        
50
    function _afterSync() internal {
51
        if(!(_syncCurrency == CurrencyLibrary.NATIVE)){
52
            RemittanceCurrency = _syncCurrency;
53
            RemittanceAmount = 0;
54
        }
55

                            
                        
56
    }      
57

                            
                        
58

                            
                        
59
}
60

                            
                        
61

                            
                        

Lines covered: 0 / 25 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {ActionFuzzBase, ActionCallbacks} from "test/trailofbits/ActionFuzzBase.sol";
5
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
6
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
7
import {PoolKey} from "src/types/PoolKey.sol";
8
import {Actions} from "src/test/ActionsRouter.sol";
9
import {BalanceDelta, BalanceDeltaLibrary} from "src/types/BalanceDelta.sol";
10
import {IHooks} from "src/interfaces/IHooks.sol";
11
import {StateLibrary} from "src/libraries/StateLibrary.sol";
12
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {TickMath} from "src/libraries/TickMath.sol";
15
import {SwapMath} from "src/libraries/SwapMath.sol";
16
import {FullMath} from "src/libraries//FullMath.sol";
17
import {ProtocolFeeLibrary} from "src/libraries/ProtocolFeeLibrary.sol";
18

                            
                        
19
contract TakeActionProps is ActionFuzzBase {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using StateLibrary for IPoolManager;
23
    using TransientStateLibrary for IPoolManager;
24
    using ProtocolFeeLibrary for uint16;
25

                            
                        
26
    Currency _takeCurrency;
27
    address _takeActor;
28

                            
                        
29
    uint256 _takeAmount;
30
    uint256 _takeActorBalanceBefore;
31
    uint256 _takeSingletonBalanceBefore;
32

                            
                        
33
    int256 _takeActorCurrencyDeltaBefore;
34

                            
                        
35
    function addTake(uint8 currency1I, uint256 amount) public {
36
        Currency c1 = Currencies[clampBetween(currency1I, 0, NUMBER_CURRENCIES-1)];
37

                            
                        
38
        bytes memory takeParams = abi.encode(c1, address(actionsRouter), amount);
39

                            
                        
40
        bytes memory beforeTakeCbParam = _encodeHarnessCallback(ActionCallbacks.BEFORE_TAKE, takeParams);
41

                            
                        
42
        actions.push(Actions.HARNESS_CALLBACK);
43
        params.push(beforeTakeCbParam);
44

                            
                        
45
        actions.push(Actions.TAKE);
46
        params.push(takeParams);
47

                            
                        
48
        bytes memory afterTakeCbParam = _encodeHarnessCallback(ActionCallbacks.AFTER_TAKE, new bytes(0));
49
        actions.push(Actions.HARNESS_CALLBACK);
50
        params.push(afterTakeCbParam);
51

                            
                        
52
    }
53

                            
                        
54
    function _beforeTake(bytes memory preTakeParams) internal {
55
        (_takeCurrency, _takeActor, _takeAmount) = abi.decode(preTakeParams, (Currency, address, uint256));
56

                            
                        
57
        _takeActorBalanceBefore = _takeCurrency.balanceOf(_takeActor);
58
        _takeSingletonBalanceBefore = _takeCurrency.balanceOf(address(manager));
59
        _takeActorCurrencyDeltaBefore = manager.currencyDelta(_takeActor, _takeCurrency);
60

                            
                        
61
        // assert actor currency delta is less than or equal to the pool balance
62
        _verifyGlobalProperties(_takeActor, _takeCurrency);
63
    }
64

                            
                        
65
    function _afterTake() internal {
66
        uint256 actorBalanceAfter = _takeCurrency.balanceOf(_takeActor);
67
        uint256 singletonBalanceAfter = _takeCurrency.balanceOf(address(manager));
68

                            
                        
69
        int256 expectedDelta = _takeActorCurrencyDeltaBefore - int256(_takeAmount);
70
        int256 actualDelta = manager.currencyDelta(_takeActor, _takeCurrency);
71
        // UNI-TAKE-1
72
        assertEq(expectedDelta, actualDelta, "After executing take(), the user's currencyDelta should be the difference between their previous delta and the amount taken");
73
        // UNI-TAKE-2
74
        assertEq(_takeActorBalanceBefore + _takeAmount, actorBalanceAfter, "After executing take(), the user's balance should increase by the amount taken.");
75
        // UNI-TAKE-3
76
        assertEq(_takeSingletonBalanceBefore - _takeAmount, singletonBalanceAfter, "After executing take(), the singleton's balance should decrease by the amount taken.");
77

                            
                        
78
        _verifyGlobalProperties(_takeActor, _takeCurrency);
79
        _addToActorsDebts(address(_takeActor), _takeCurrency, _takeAmount);
80
    }      
81

                            
                        
82

                            
                        
83
}
84

                            
                        

Lines covered: 0 / 34 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
5

                            
                        
6
import {IHooks} from "src/interfaces/IHooks.sol";
7
import {Hooks} from "src/libraries/Hooks.sol";
8
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
9

                            
                        
10
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
11
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
12
import {PoolKey} from "src/types/PoolKey.sol";
13
import {BalanceDelta} from "src/types/BalanceDelta.sol";
14
import {StateLibrary} from "src/libraries/StateLibrary.sol";
15
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
16

                            
                        
17
import {PoolTestBase} from "src/test/PoolTestBase.sol";
18
import {PoolModifyLiquidityTest} from "src/test/PoolModifyLiquidityTest.sol";
19
import {Deployers} from "test/utils/Deployers.sol";
20
import {CurrencySettler} from "test/utils/CurrencySettler.sol";
21

                            
                        
22
import {IActor} from "./IActor.sol";
23
import {PropertiesAsserts} from "../PropertiesHelper.sol";
24
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
25

                            
                        
26

                            
                        
27
contract DonationActor is PropertiesAsserts, PoolTestBase, IActor {
28
    using PoolIdLibrary for PoolKey;
29
    using StateLibrary for IPoolManager;
30
    using CurrencyLibrary for Currency;
31
    using Hooks for IHooks;
32
    using LPFeeLibrary for uint24;
33

                            
                        
34
    address Harness;
35

                            
                        
36
    constructor(IPoolManager _manager) PoolTestBase(_manager) {
37
        Harness = msg.sender;
38
    }
39
    
40
    struct CallbackData {
41
        address sender;
42
        PoolKey key;
43
        uint256 amount0;
44
        uint256 amount1;
45
        bytes hookData;
46
    }
47

                            
                        
48
    function Donate(PoolKey memory key, uint256 amount0, uint256 amount1)
49
        external
50
        payable
51
        returns (BalanceDelta delta)
52
    {
53
        delta = abi.decode(
54
            manager.unlock(abi.encode(CallbackData(msg.sender, key, amount0, amount1, new bytes(0)))), (BalanceDelta)
55
        );
56

                            
                        
57
        uint256 ethBalance = address(this).balance;
58
        if (ethBalance > 0) {
59
            CurrencyLibrary.NATIVE.transfer(msg.sender, ethBalance);
60
        }
61
    }
62

                            
                        
63

                            
                        
64

                            
                        
65
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
66
        require(msg.sender == address(manager));
67

                            
                        
68
        CallbackData memory data = abi.decode(rawData, (CallbackData));
69

                            
                        
70
        (,, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender, address(this));
71
        (,, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender, address(this));
72

                            
                        
73
        require(deltaBefore0 == 0, "deltaBefore0 is not 0");
74
        require(deltaBefore1 == 0, "deltaBefore1 is not 0");
75

                            
                        
76
        BalanceDelta delta = manager.donate(data.key, data.amount0, data.amount1, data.hookData);
77

                            
                        
78
        (,, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this));
79
        (,, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this));
80

                            
                        
81
        require(deltaAfter0 == -int256(data.amount0), "deltaAfter0 is not equal to -int256(data.amount0)");
82
        require(deltaAfter1 == -int256(data.amount1), "deltaAfter1 is not equal to -int256(data.amount1)");
83

                            
                        
84

                            
                        
85
        if (deltaAfter0 < 0) {
86
            // obtain tokens from harness
87
            MockERC20(Currency.unwrap(data.key.currency0)).transferFrom(Harness, address(this), uint256(-deltaAfter0));
88
            CurrencySettler.settle(data.key.currency0, manager, data.sender, uint256(-deltaAfter0), false);
89
        } 
90
        if (deltaAfter1 < 0){ 
91
            // obtain tokens from harness
92
            MockERC20(Currency.unwrap(data.key.currency1)).transferFrom(Harness, address(this), uint256(-deltaAfter1));
93
            CurrencySettler.settle(data.key.currency1, manager, data.sender, uint256(-deltaAfter1), false);
94
        }
95
        if (deltaAfter0 > 0) {
96
            // unhittable?
97
            assert(false);
98
            CurrencySettler.take(data.key.currency0, manager, data.sender, uint256(deltaAfter0), false);
99
            // send tokens back to harness
100
            data.key.currency0.transfer(Harness, uint256(deltaAfter0));
101
        }
102
        if (deltaAfter1 > 0){ 
103
            // unhittable?
104
            assert(false);
105
            CurrencySettler.take(data.key.currency1, manager, data.sender, uint256(deltaAfter1), false);
106
            // send tokens back to harness
107
            data.key.currency1.transfer( Harness, uint256(deltaAfter1));
108
        }
109

                            
                        
110
        return abi.encode(delta);
111
    }
112

                            
                        
113
    function proxyApprove(Currency token, address spender) public {
114
        MockERC20(Currency.unwrap(token)).approve(spender, type(uint256).max);
115
    }
116

                            
                        
117
}

Lines covered: 0 / 141 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
5

                            
                        
6
import {IHooks} from "src/interfaces/IHooks.sol";
7
import {Hooks} from "src/libraries/Hooks.sol";
8
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
9

                            
                        
10
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
11
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
12
import {PoolKey} from "src/types/PoolKey.sol";
13
import {BalanceDelta} from "src/types/BalanceDelta.sol";
14
import {StateLibrary} from "src/libraries/StateLibrary.sol";
15
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
16
import {TickMath} from "src/libraries/TickMath.sol";
17

                            
                        
18
import {PoolTestBase} from "src/test/PoolTestBase.sol";
19
import {PoolModifyLiquidityTest} from "src/test/PoolModifyLiquidityTest.sol";
20
import {Deployers} from "test/utils/Deployers.sol";
21
import {CurrencySettler} from "test/utils/CurrencySettler.sol";
22

                            
                        
23
import {IActor} from "./IActor.sol";
24
import {PropertiesAsserts} from "../PropertiesHelper.sol";
25
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
26

                            
                        
27
import {SwapActor} from "./SwapActor.sol";
28
import {LiquidityActor} from "./LiquidityActor.sol";
29
import {DonationActor} from "./DonationActor.sol";
30

                            
                        
31

                            
                        
32
contract EndToEnd is PropertiesAsserts, Deployers {
33
    using PoolIdLibrary for PoolKey;
34
    using CurrencyLibrary for Currency;
35

                            
                        
36
    PoolKey[] DeployedPools;
37
    mapping(PoolId => bool) PoolInitialized;
38
    Currency[] Currencies;
39

                            
                        
40

                            
                        
41
    // actors
42
    LiquidityActor[] LiquidityActors;
43
    DonationActor[] DonationActors;
44
    SwapActor[] SwapActors;
45

                            
                        
46

                            
                        
47
    uint NUMBER_CURRENCIES = 2;
48
    uint NUMBER_LIQUIDITY_ACTORS = 1;
49
    uint NUMBER_DONATION_ACTORS = 1;
50
    uint NUMBER_SWAP_ACTORS = 1;
51

                            
                        
52
    constructor () payable {
53
        Deployers.deployFreshManagerAndRouters();
54

                            
                        
55
        // Initialize currencies
56
        for (uint i = 0; i < NUMBER_CURRENCIES; i++) {
57
            Currencies.push(deployMintAndApproveCurrency());
58
        }
59

                            
                        
60
        for (uint i = 0; i < NUMBER_LIQUIDITY_ACTORS; i++) {
61
            LiquidityActor a = new LiquidityActor(manager);
62
            LiquidityActors.push(a);
63
            _setupActorApprovals(a);
64
        }
65

                            
                        
66
        for (uint i = 0; i < NUMBER_DONATION_ACTORS; i++) {
67
            DonationActor a = new DonationActor(manager);
68
            DonationActors.push(a);
69
            _setupActorApprovals(a);
70
        }
71

                            
                        
72
        for (uint i = 0; i < NUMBER_SWAP_ACTORS; i++) {
73
            SwapActor a = new SwapActor(manager);
74
            SwapActors.push(a);
75
            _setupActorApprovals(a);
76
        }
77
    }
78

                            
                        
79
    function _setupActorApprovals(IActor c) internal {
80
        address[9] memory toApprove = [
81
            address(swapRouter),
82
            address(swapRouterNoChecks),
83
            address(modifyLiquidityRouter),
84
            address(modifyLiquidityNoChecks),
85
            address(donateRouter),
86
            address(takeRouter),
87
            address(claimsRouter),
88
            address(nestedActionRouter.executor()),
89
            address(actionsRouter)
90
        ];
91

                            
                        
92
        for(uint i = 0; i < NUMBER_CURRENCIES; i++) {
93
            Currency cur = Currencies[i];
94
            // By giving actors approval to this contracts funds, we allow them to search the full totalSupply space.
95
            // If we distributed tokens to each actor, they would be limited to exploration using tokens up to 
96
            // totalSupply/numActors.
97
            MockERC20(Currency.unwrap(cur)).approve(address(c), type(uint256).max);
98

                            
                        
99
            for( uint approveI=0; approveI< toApprove.length; approveI++) {
100
                c.proxyApprove(cur, toApprove[approveI]);
101
            }
102
        }
103
    }
104

                            
                        
105
    function _clampLiquidityActor(uint8 actorIndex) internal returns (LiquidityActor) {
106
        actorIndex = uint8(clampBetween(actorIndex, 0, NUMBER_LIQUIDITY_ACTORS-1));
107
        emit LogUint256("LiquidityActor index", actorIndex);
108
        return LiquidityActors[actorIndex];
109
    }
110

                            
                        
111
    function _clampDonationActor(uint8 actorIndex) internal returns (DonationActor) {
112
        actorIndex = uint8(clampBetween(actorIndex, 0, NUMBER_DONATION_ACTORS-1));
113
        emit LogUint256("DonationActor index", actorIndex);
114
        return DonationActors[actorIndex];
115
    }
116
    function _clampSwapActor(uint8 actorIndex) internal returns (SwapActor) {
117
        actorIndex = uint8(clampBetween(actorIndex, 0, NUMBER_SWAP_ACTORS-1));
118
        emit LogUint256("SwapActor index", actorIndex);
119
        return SwapActors[actorIndex];
120
    }
121

                            
                        
122
    function _clampToValidCurrencies(uint8 currency1I, uint8 currency2I) internal returns (Currency, Currency) {
123
        uint c1 = clampBetween(currency1I, 0, NUMBER_CURRENCIES-1);
124
        uint c2 = clampBetween(currency2I, 0, NUMBER_CURRENCIES-1);
125
        require(c1 != c2);
126

                            
                        
127
        Currency cur1 = Currencies[c1];
128
        Currency cur2 = Currencies[c2];
129
        if (cur1 >= cur2) {
130
            emit LogAddress("address 1", address(Currency.unwrap(cur2)));
131
            emit LogAddress("address 2", address(Currency.unwrap(cur1)));
132
            return (cur2, cur1);
133
        } else {
134
            emit LogAddress("address 1", address(Currency.unwrap(cur1)));
135
            emit LogAddress("address 2", address(Currency.unwrap(cur2)));
136
            return (cur1, cur2);
137
        }
138
    }
139

                            
                        
140
    function _clampToValidPool(uint poolIndex) internal returns ( PoolKey memory) {
141
        poolIndex = clampBetween(poolIndex, 0, DeployedPools.length-1);
142
        emit LogUint256("Pool index", poolIndex);
143
        return DeployedPools[poolIndex];
144
    }
145

                            
                        
146
    function _clampToUsableTicks(int24 minTick, int24 maxTick, PoolKey memory poolKey) internal returns (int24, int24) {
147
        int24 minUsableTick = TickMath.minUsableTick(poolKey.tickSpacing);
148
        int24 maxUsableTick = TickMath.maxUsableTick(poolKey.tickSpacing);
149

                            
                        
150
        emit LogInt256("minUsableTick", minUsableTick);
151
        emit LogInt256("maxUsableTick", maxUsableTick);
152

                            
                        
153
        minTick = int24(clampBetween(minTick, minUsableTick, maxUsableTick));
154
        maxTick = int24(clampBetween(maxTick, minUsableTick, maxUsableTick));
155

                            
                        
156
        if (maxTick < minTick) {
157
            int24 tmp = minTick;
158
            minTick = maxTick;
159
            maxTick = tmp;
160
        }
161

                            
                        
162
        emit LogInt256("minTick", minTick);
163
        emit LogInt256("maxTick", maxTick);
164
        return (minTick, maxTick);
165
    }
166

                            
                        
167
    /// @custom:notes This works the same way as e2e_createPool, but clamps inputs to correct values to help our coverage.
168
    function e2e_CreatePool_Coverage(uint8 currency1I, uint8 currency2I, int16 tickSpacing, uint256 startPrice, uint256 fee) public {
169
        Currency c1;
170
        Currency c2;
171
        (c1, c2) =  _clampToValidCurrencies(currency1I, currency2I);
172
        int24 tickSpacingClamped = int24(clampBetween(tickSpacing,1, type(int16).max));
173
        emit LogInt256("tickSpacingClamped", tickSpacingClamped);
174

                            
                        
175
        uint256 initialPrice = clampBetween(startPrice, 4295128739, 1461446703485210103287273052203988822378723970342-1);
176
        emit LogUint256("initialPrice", initialPrice);
177
        
178
        uint256 initialFee = clampBetween(fee, 0, 1_000_000);
179
        emit LogUint256("initialFee", fee);
180

                            
                        
181
        PoolKey memory k = PoolKey(c1, c2, uint24(initialFee), tickSpacingClamped, IHooks(address(0)));
182
        PoolId id = k.toId();
183
        if (PoolInitialized[id]){
184
            return;
185
        }
186

                            
                        
187
        int24 tick;
188
        try manager.initialize(k, uint160(initialPrice), ZERO_BYTES) returns (int24 t) {
189
            tick = t;
190
        }            
191
        catch  {
192
            // todo: REVISIT
193
            // assertWithMsg(false, "manager.initialize() threw an unknown exception. investigate");
194

                            
                        
195
            return;
196
        }
197
        
198
        DeployedPools.push(k);
199
        PoolInitialized[id] = true;
200

                            
                        
201
        e2e_ProvideLiquidityFullRange(0, 0, 1 ether);
202
    }
203

                            
                        
204

                            
                        
205
    /// @custom:notes This function facilitates the creation of new pools for other properties.
206
    function e2e_CreatePool(uint8 currency1I, uint8 currency2I, int16 tickSpacing, uint256 startPrice, uint256 fee) public {
207
        Currency c1;
208
        Currency c2;
209
        (c1, c2) =  _clampToValidCurrencies(currency1I, currency2I);
210
        int24 tickSpacingClamped = int24(clampBetween(tickSpacing,1, type(int16).max));
211
        emit LogInt256("tickSpacingClamped", tickSpacingClamped);
212

                            
                        
213
        uint256 initialPrice = startPrice;
214
        emit LogUint256("initialPrice", initialPrice);
215
        emit LogUint256("initialFee", fee);
216

                            
                        
217
        PoolKey memory k = PoolKey(c1, c2, uint24(fee), tickSpacingClamped, IHooks(address(0)));
218
        PoolId id = k.toId();
219
        bool poolinitialized = PoolInitialized[id];
220

                            
                        
221
        int24 tick;
222
        try manager.initialize(k, uint160(initialPrice), ZERO_BYTES) returns (int24 t) {
223
            tick = t;
224
        }            
225
        catch (bytes memory data) {
226
            if (bytes4(data) == bytes4(keccak256(bytes("PoolAlreadyInitialized()")) )){
227
                // allowable exception iff poolInitialized
228
                assertWithMsg(poolinitialized, "initialize() reverted with PoolAlreadyInitialized() but pool is not initialized");
229
                return;
230
            }
231
            if (bytes4(data) == bytes4(keccak256(bytes("InvalidSqrtPrice(uint160)")) )){
232
                // allowable exception iff initialPrice is outside the valid range
233
                assertWithMsg(initialPrice < 4295128739 || initialPrice > 1461446703485210103287273052203988822378723970342-1, "initialize() reverted with InvalidSqrtPrice() but initialPrice is within valid range");
234
                return;
235
            }
236
            if (bytes4(data) == bytes4(keccak256(bytes("LPFeeTooLarge(uint24)")) )){
237
                // allowable exception iff fee is larger than 1_000_000
238
                assertGt(fee, 1_000_000, "initialize() reverted with LPFeeTooLarge() but initialFee is within valid range");
239
                return;
240
            }
241
            // assertWithMsg(false, "manager.initialize() threw an unknown exception. investigate");
242
            return;
243
        }
244
        // we should have reverted if pool was initialized
245
        assertWithMsg(!poolinitialized, "initialize() did not revert, but pool is not initialized");
246

                            
                        
247
        // verify tick is valid
248
        emit LogInt256("tick", tick);
249
        assertGte(tick, TickMath.MIN_TICK, "tick below valid range");
250
        assertLte(tick, TickMath.MAX_TICK, "tick above valid range");
251

                            
                        
252
        // todo: alternate property about tick width?
253
        
254
        DeployedPools.push(k);
255
        PoolInitialized[id] = true;
256

                            
                        
257
        e2e_ProvideLiquidityFullRange(0, 0, 1 ether);
258
    }
259

                            
                        
260
    function e2e_DonateToLiquidity(uint8 actorIndex, uint poolIndex, uint256 amount0, uint256 amount1) public {
261
        DonationActor actor = _clampDonationActor(actorIndex);
262
        PoolKey memory poolKey = _clampToValidPool(poolIndex);
263
        actor.Donate(poolKey, amount0, amount1);
264
    }
265

                            
                        
266

                            
                        
267
    function e2e_ProvideLiquidity(uint8 actorIndex, uint poolIndex, int24 minTick, int24 maxTick, int256 liquidityDelta) public {
268
        LiquidityActor actor = _clampLiquidityActor(actorIndex);
269
        PoolKey memory poolKey = _clampToValidPool(poolIndex);
270

                            
                        
271
        (minTick, maxTick) = _clampToUsableTicks(minTick, maxTick, poolKey);
272
        actor.ProvideLiquidity(poolKey, minTick, maxTick, liquidityDelta);
273
    }
274

                            
                        
275
    /// @custom:property delta0 and delta1 must be greater than zero when providing LP for full-range liquidity
276
    /// @custom:precondition Pools Created (e2e_CreatePool)
277
    function e2e_ProvideLiquidityFullRange(uint8 actorIndex, uint poolIndex, int256 liquidityDelta) public {
278
        LiquidityActor actor = _clampLiquidityActor(actorIndex);
279
        PoolKey memory poolKey = _clampToValidPool(poolIndex);
280
        int24 minTick = TickMath.minUsableTick(poolKey.tickSpacing);
281
        int24 maxTick = TickMath.maxUsableTick(poolKey.tickSpacing);
282

                            
                        
283
        uint256 delta0;
284
        uint256 delta1;
285
        (delta0, delta1) = actor.ProvideLiquidity(poolKey, minTick, maxTick, liquidityDelta);
286

                            
                        
287
    }
288

                            
                        
289
    function e2e_SwapOneDirection(uint8 actorIndex, uint poolIndex, int256 amountSpecified, bool zeroForOne) public {
290
        SwapActor actor = _clampSwapActor(actorIndex);
291
        PoolKey memory poolKey = _clampToValidPool(poolIndex);
292

                            
                        
293
        actor.swapOneDirection(zeroForOne, amountSpecified, poolKey);
294
    }
295

                            
                        
296
    function e2e_SwapBidirectional(uint8 actorIndex, uint poolIndex, int256 amountSpecified, bool zeroForOne)  public {
297
        SwapActor actor = _clampSwapActor(actorIndex);
298
        PoolKey memory poolKey = _clampToValidPool(poolIndex);
299

                            
                        
300
        actor.swapBiDirectional(zeroForOne, amountSpecified, poolKey);
301
    }
302
}

Lines covered: 0 / 80 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {IHooks} from "src/interfaces/IHooks.sol";
5
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
6

                            
                        
7
import {Hooks} from "src/libraries/Hooks.sol";
8
import {TickMath} from "src/libraries/TickMath.sol";
9
import {Deployers} from "test/utils/Deployers.sol";
10
import {StateLibrary} from "src/libraries/StateLibrary.sol";
11
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
12
import {PoolKey} from "src/types/PoolKey.sol";
13
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
14

                            
                        
15
import {PropertiesAsserts} from "../PropertiesHelper.sol";
16
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
17

                            
                        
18

                            
                        
19
contract Harness is Deployers, PropertiesAsserts {
20
    using PoolIdLibrary for PoolKey;
21
    using CurrencyLibrary for Currency;
22
    using StateLibrary for IPoolManager;
23
    using SwapInfoLibrary for SwapInfo;
24

                            
                        
25
    uint256 constant MAX_CURRENCIES = 5;
26

                            
                        
27
    PoolId poolId;
28

                            
                        
29
    constructor() payable {
30
        Deployers.deployFreshManagerAndRouters();
31
    }
32

                            
                        
33
    
34

                            
                        
35
    function prop_CreatePool(int16 tickSpacing, uint256 startPrice, uint256 fee) public {
36
        if (address(Currency.unwrap(currency0)) != address(0)) {
37
            return;
38
        }
39

                            
                        
40
        int24 tickSpacingClamped = int24(clampBetween(tickSpacing,1, type(int16).max));
41
        uint256 initialPrice = clampBetween(startPrice, TickMath.MIN_SQRT_PRICE,TickMath.MAX_SQRT_PRICE);
42
        uint256 initialFee = clampBetween(fee, 0, 1_000_000);
43

                            
                        
44
        Deployers.deployMintAndApprove2Currencies();
45
        key = PoolKey(currency0, currency1, uint24(initialFee), tickSpacingClamped, IHooks(address(0)));
46
        poolId = key.toId();
47
        manager.initialize(key, uint160(initialPrice), ZERO_BYTES);
48

                            
                        
49
        modifyLiquidityRouter.modifyLiquidity(
50
            key,
51
            IPoolManager.ModifyLiquidityParams(
52
                TickMath.minUsableTick(tickSpacingClamped),
53
                TickMath.maxUsableTick(tickSpacingClamped), 10_000 ether, 0),
54
            ZERO_BYTES
55
        );
56

                            
                        
57
        // make sure the corpus contains some more extreme conditions
58
        uint leeway = 10;
59
        if (int256(tickSpacingClamped) < int256(leeway)) {
60
            emit LogInt256("tickSpacingClamped", tickSpacingClamped);
61
        } else if (int256(tickSpacingClamped) > int256(type(uint16).max - leeway)) {
62
            emit LogInt256("tickSpacingClamped", tickSpacingClamped);
63
        } else {
64
            emit LogInt256("tickSpacingClamped", tickSpacingClamped);
65
        }
66

                            
                        
67
        if (initialPrice < TickMath.MIN_SQRT_PRICE + leeway) {
68
            emit LogUint256("initialPrice", initialPrice);
69
        } else if (initialPrice > TickMath.MAX_SQRT_PRICE - leeway) {
70
            emit LogUint256("initialPrice", initialPrice);
71
        } else {
72
            emit LogUint256("initialPrice", initialPrice);
73
        }
74

                            
                        
75
        if (initialFee < leeway) {
76
            emit LogUint256("initialFee", initialFee);
77
        } else if (initialFee > 1_000_000 - leeway) {
78
            emit LogUint256("initialFee", initialFee);
79
        } else {
80
            emit LogUint256("initialFee", initialFee);
81
        }
82
    }
83

                            
                        
84
    // Swap into and out of a pair. ensure you're left with less tokens than you started with.
85
    // When swapping out of the pair, this function requests all the tokens it swapped in to be swapped back out.
86
    function prop_BiDirectionalPathExactInput(bool zeroForOne, int256 amount) public {
87
        if (address(Currency.unwrap(currency0)) == address(0)) {
88
            return;
89
        }
90
        Currency fromCurrency = zeroForOne ? currency0 : currency1;
91
        Currency toCurrency = zeroForOne ? currency1 : currency0;
92

                            
                        
93
        SwapInfo memory swap1Results = SwapInfoLibrary.initialize(fromCurrency, toCurrency, address(this));
94
        
95
        swap(key, zeroForOne, amount, ZERO_BYTES);
96

                            
                        
97
        swap1Results.captureSwapResults();
98

                            
                        
99
        emit LogInt256("Swap 1 amount", amount);
100
        emit LogInt256("Swap 1 fromDelta", swap1Results.fromDelta);
101
        emit LogInt256("Swap 1 toDelta", swap1Results.toDelta);
102

                            
                        
103
        assert(swap1Results.fromDelta <= 0);
104
        assert(swap1Results.toDelta >= 0);
105

                            
                        
106
        // now swap in the opposite direction using the exact amount we received
107
        int256 newAmount = -1 * swap1Results.toDelta;
108
        SwapInfo memory swap2Results = SwapInfoLibrary.initialize(toCurrency, fromCurrency, address(this));
109
        swap(key, !zeroForOne, newAmount, ZERO_BYTES);
110
        swap2Results.captureSwapResults();
111

                            
                        
112
        emit LogInt256("Swap 2 amount", newAmount);
113
        emit LogInt256("Swap 2 fromDelta", swap2Results.fromDelta);
114
        emit LogInt256("Swap 2 toDelta", swap2Results.toDelta);
115

                            
                        
116
        assert(swap2Results.fromDelta <= 0);
117
        assert(swap2Results.toDelta >= 0);
118

                            
                        
119
        // now actually verify the property
120
        int256 fromBalanceDifference = swap2Results.toBalanceAfter - swap1Results.fromBalanceBefore;
121
        int256 toBalanceDifference = swap2Results.fromBalanceAfter - swap1Results.toBalanceBefore;
122
        emit LogInt256("fromBalanceDifference", fromBalanceDifference);
123
        emit LogInt256("toBalanceDifference", toBalanceDifference);
124
        assertLt(fromBalanceDifference, 0, "Must not have more tokens than started with (from)");
125
        // re-add this if using a static newAmount
126
        assertLte(toBalanceDifference, 0, "Must not have more tokens than started with (to)");
127
    }
128

                            
                        
129
    // Swap into and out of a pair. ensure you're left with less tokens than you started with.
130
    function prop_BidirectionalPath(bool zeroForOne, int256 amount, uint128 reverseAmount) public {
131
        if (address(Currency.unwrap(currency0)) == address(0)) {
132
            return;
133
        }
134
        Currency fromCurrency = zeroForOne ? currency0 : currency1;
135
        Currency toCurrency = zeroForOne ? currency1 : currency0;
136

                            
                        
137
        SwapInfo memory swap1Results = SwapInfoLibrary.initialize(fromCurrency, toCurrency, address(this));
138
        
139
        swap(key, zeroForOne, amount, ZERO_BYTES);
140

                            
                        
141
        swap1Results.captureSwapResults();
142

                            
                        
143
        emit LogInt256("Swap 1 amount", amount);
144
        emit LogInt256("Swap 1 fromDelta", swap1Results.fromDelta);
145
        emit LogInt256("Swap 1 toDelta", swap1Results.toDelta);
146

                            
                        
147
        assert(swap1Results.fromDelta <= 0);
148
        assert(swap1Results.toDelta >= 0);
149

                            
                        
150
        // now swap in the opposite direction using exact input between 1 and the original swapped amount.
151
        int256 newAmount = -1 * int256(clampBetween(reverseAmount, 1, uint256(swap1Results.toDelta)));
152
        SwapInfo memory swap2Results = SwapInfoLibrary.initialize(toCurrency, fromCurrency, address(this));
153
        swap(key, !zeroForOne, newAmount, ZERO_BYTES);
154
        swap2Results.captureSwapResults();
155

                            
                        
156
        emit LogInt256("Swap 2 amount", newAmount);
157
        emit LogInt256("Swap 2 fromDelta", swap2Results.fromDelta);
158
        emit LogInt256("Swap 2 toDelta", swap2Results.toDelta);
159

                            
                        
160
        assert(swap2Results.fromDelta <= 0);
161
        assert(swap2Results.toDelta >= 0);
162

                            
                        
163
        // now actually verify the property
164
        int256 fromBalanceDifference = swap2Results.toBalanceAfter - swap1Results.fromBalanceBefore;
165
        int256 toBalanceDifference = swap2Results.fromBalanceAfter - swap1Results.toBalanceBefore;
166
        emit LogInt256("fromBalanceDifference", fromBalanceDifference);
167
        emit LogInt256("toBalanceDifference", toBalanceDifference);
168
        assertLt(fromBalanceDifference, 0, "Must not have more tokens than started with (from)");
169
    }
170
}

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import {Currency, CurrencyLibrary} from "src/types/Currency.sol";
5

                            
                        
6
interface IActor{
7
    function proxyApprove(Currency token, address spender) external;
8
}

Lines covered: 0 / 15 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {IHooks} from "src/interfaces/IHooks.sol";
5
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
6

                            
                        
7
import {Hooks} from "src/libraries/Hooks.sol";
8
import {TickMath} from "src/libraries/TickMath.sol";
9
import {Deployers} from "test/utils/Deployers.sol";
10
import {StateLibrary} from "src/libraries/StateLibrary.sol";
11
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
12
import {PoolKey} from "src/types/PoolKey.sol";
13
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
14

                            
                        
15
import {PropertiesAsserts} from "../PropertiesHelper.sol";
16

                            
                        
17

                            
                        
18
struct SwapInfo {
19
    Currency fromCurrency;
20
    Currency toCurrency;
21
    address User;
22
    int256 fromBalanceBefore;
23
    int256 toBalanceBefore;
24
    int256 fromBalanceAfter;
25
    int256 toBalanceAfter;
26
    int256 fromDelta;
27
    int256 toDelta;
28
}
29

                            
                        
30
library SwapInfoLibrary {
31
   function initialize(Currency fromCurrency, Currency toCurrency, address user) internal view returns (SwapInfo memory) {
32
        return SwapInfo({
33
            User: user,
34
            fromCurrency: fromCurrency,
35
            toCurrency: toCurrency,
36
            fromBalanceBefore: int256(fromCurrency.balanceOf(user)),
37
            toBalanceBefore: int256(toCurrency.balanceOf(user)),
38
            fromBalanceAfter: 0,
39
            toBalanceAfter: 0,
40
            fromDelta: 0,
41
            toDelta: 0
42
        });
43
   }
44

                            
                        
45
   function captureSwapResults(SwapInfo memory s) internal view {
46
        s.fromBalanceAfter = int256(s.fromCurrency.balanceOf(s.User));
47
        s.toBalanceAfter = int256(s.toCurrency.balanceOf(s.User));
48
        s.fromDelta = int256(s.fromBalanceAfter) - int256(s.fromBalanceBefore);
49
        s.toDelta = int256(s.toBalanceAfter) - int256(s.toBalanceBefore);
50
   }
51
}
52
using SwapInfoLibrary for SwapInfo global;
53

                            
                        

Lines covered: 0 / 61 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {IHooks} from "src/interfaces/IHooks.sol";
5
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
6
import {Hooks} from "src/libraries/Hooks.sol";
7
import {TickMath} from "src/libraries/TickMath.sol";
8
import {Deployers} from "test/utils/Deployers.sol";
9
import {StateLibrary} from "src/libraries/StateLibrary.sol";
10
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
11
import {PoolKey} from "src/types/PoolKey.sol";
12
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
13
import {PropertiesAsserts} from "../PropertiesHelper.sol";
14
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
15
import {PoolModifyLiquidityTest} from "src/test/PoolModifyLiquidityTest.sol";
16
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
17
import {IActor} from "./IActor.sol";
18
import {BalanceDelta} from "src/types/BalanceDelta.sol";
19
import {CurrencySettler} from "test/utils/CurrencySettler.sol";
20
import {PoolTestBase} from "src/test/PoolTestBase.sol";
21
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
22

                            
                        
23
contract LiquidityActor is PropertiesAsserts, PoolTestBase, IActor {
24
    using PoolIdLibrary for PoolKey;
25
    using StateLibrary for IPoolManager;
26
    using CurrencyLibrary for Currency;
27
    using Hooks for IHooks;
28
    using LPFeeLibrary for uint24;
29

                            
                        
30
    struct LpPosition {
31
        PoolKey poolKey;
32
        int24 minTick;
33
        int24 maxTick;
34
        uint256 liquidity;
35
        bytes32 salt;
36
    }
37

                            
                        
38
    mapping(PoolId => mapping(uint256 => LpPosition)) lpPositions;
39
    mapping(PoolId => uint256) lpPositionCount;
40
    address Harness;
41
    
42
    constructor(IPoolManager _manager) PoolTestBase(_manager) {
43
        Harness = msg.sender;
44
    }
45

                            
                        
46
    function _getLatestSalt(PoolId poolId) internal returns (uint256) {
47
        uint256 nextSalt = lpPositionCount[poolId];
48
        lpPositionCount[poolId] += 1;
49
        return nextSalt;
50
    }
51

                            
                        
52
    function ProvideLiquidity(PoolKey memory poolKey, int24 minTick, int24 maxTick, int256 liqDelta) public returns (uint256 delta0,uint256 delta1) {
53
        PoolId poolId = poolKey.toId();
54
        uint256 salt = _getLatestSalt(poolId);
55

                            
                        
56
        uint256 cur0Before = poolKey.currency0.balanceOf(msg.sender);
57
        uint256 cur1Before = poolKey.currency1.balanceOf(msg.sender);
58

                            
                        
59

                            
                        
60
        IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams(
61
            minTick, 
62
            maxTick, 
63
            liqDelta, 
64
            bytes32(salt));
65
        try manager.unlock(abi.encode(CallbackData(address(this), poolKey, params, new bytes(0), false, false))){}
66
        catch Error(string memory reason) {
67
            emit LogString("Error in unlock");
68
            emit LogString(reason);
69
            assert(false);
70
        }
71
        emit LogUint256("Liquidity provided for position idx", salt);
72
        emit LogInt256("liquidity", liqDelta);
73
        delta0 = cur0Before - poolKey.currency0.balanceOf(msg.sender);
74
        delta1 = cur1Before - poolKey.currency1.balanceOf(msg.sender);
75
        emit LogUint256("currency 0 delta", delta0);
76
        emit LogUint256("currency 1 delta", delta1);
77
        LpPosition memory lpPosition = lpPositions[poolId][salt];
78

                            
                        
79
        // technically an invariant null-op since this function always creates new positions. Should also be verified in unlockCallback.
80
        assertGte(liqDelta + int256(lpPosition.liquidity), 0, "Removed more liquidity than was in the position");
81

                            
                        
82
        lpPositions[poolId][salt] = LpPosition(poolKey, minTick, maxTick, manager.getPosition(
83
            poolId, address(this), minTick, maxTick, bytes32(salt)
84
        ).liquidity, bytes32(salt));
85
    }
86

                            
                        
87
    function proxyApprove(Currency token, address spender) public {
88
        MockERC20(Currency.unwrap(token)).approve(spender, type(uint256).max);
89
    }
90

                            
                        
91
    struct CallbackData {
92
        address sender;
93
        PoolKey key;
94
        IPoolManager.ModifyLiquidityParams params;
95
        bytes hookData;
96
        bool settleUsingBurn;
97
        bool takeClaims;
98
    }
99

                            
                        
100
    function unlockCallback(bytes calldata rawData) external override returns (bytes memory) {
101
        require(msg.sender == address(manager));
102

                            
                        
103
        CallbackData memory data = abi.decode(rawData, (CallbackData));
104

                            
                        
105
        uint128 liquidityBefore = manager.getPosition(
106
            data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt
107
        ).liquidity;
108
        (BalanceDelta delta,) = manager.modifyLiquidity(data.key, data.params, data.hookData);
109

                            
                        
110
        uint128 liquidityAfter = manager.getPosition(
111
            data.key.toId(), address(this), data.params.tickLower, data.params.tickUpper, data.params.salt
112
        ).liquidity;
113

                            
                        
114
        (,, int256 delta0) = _fetchBalances(data.key.currency0, data.sender, address(this));
115
        (,, int256 delta1) = _fetchBalances(data.key.currency1, data.sender, address(this));
116

                            
                        
117
        require(
118
            int128(liquidityBefore) + data.params.liquidityDelta == int128(liquidityAfter), "liquidity change incorrect"
119
        );
120

                            
                        
121
        if (data.params.liquidityDelta < 0) {
122
            assert(delta0 > 0 || delta1 > 0);
123
            assert(!(delta0 < 0 || delta1 < 0));
124
        } else if (data.params.liquidityDelta > 0) {
125
            assert(delta0 < 0 || delta1 < 0);
126
            assert(!(delta0 > 0 || delta1 > 0));
127
        }
128

                            
                        
129
        if (delta0 < 0) {
130
            // obtain tokens from harness
131
            MockERC20(Currency.unwrap(data.key.currency0)).transferFrom(Harness, address(this), uint256(-delta0));
132
            CurrencySettler.settle(data.key.currency0, manager, data.sender, uint256(-delta0), data.settleUsingBurn);
133
        } 
134
        if (delta1 < 0){ 
135
            // obtain tokens from harness
136
            MockERC20(Currency.unwrap(data.key.currency1)).transferFrom(Harness, address(this), uint256(-delta1));
137
            CurrencySettler.settle(data.key.currency1, manager, data.sender, uint256(-delta1), data.settleUsingBurn);
138
        }
139
        if (delta0 > 0) {
140
            CurrencySettler.take(data.key.currency0, manager, data.sender, uint256(delta0), data.takeClaims);
141
            // send tokens back to harness
142
            data.key.currency0.transfer(Harness, uint256(delta0));
143
        }
144
        if (delta1 > 0){ 
145
            CurrencySettler.take(data.key.currency1, manager, data.sender, uint256(delta1), data.takeClaims);
146
            // send tokens back to harness
147
            data.key.currency1.transfer( Harness, uint256(delta1));
148
        }
149

                            
                        
150
        return abi.encode(delta);
151
    }
152

                            
                        
153
}

Lines covered: 0 / 75 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.0;
3

                            
                        
4
import {IHooks} from "src/interfaces/IHooks.sol";
5
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
6
import {Hooks} from "src/libraries/Hooks.sol";
7
import {TickMath} from "src/libraries/TickMath.sol";
8
import {Deployers} from "test/utils/Deployers.sol";
9
import {StateLibrary} from "src/libraries/StateLibrary.sol";
10
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
11
import {PoolKey} from "src/types/PoolKey.sol";
12
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
13
import {PropertiesAsserts} from "../PropertiesHelper.sol";
14
import {PoolModifyLiquidityTest} from "src/test/PoolModifyLiquidityTest.sol";
15
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
16
import {IActor} from "./IActor.sol";
17
import {BalanceDelta} from "src/types/BalanceDelta.sol";
18
import {CurrencySettler} from "test/utils/CurrencySettler.sol";
19
import {PoolTestBase} from "src/test/PoolTestBase.sol";
20
import {LPFeeLibrary} from "src/libraries/LPFeeLibrary.sol";
21
import {SwapInfo, SwapInfoLibrary} from "./Lib.sol";
22

                            
                        
23
contract SwapActor is PropertiesAsserts, PoolTestBase, IActor {
24

                            
                        
25
    using PoolIdLibrary for PoolKey;
26
    using StateLibrary for IPoolManager;
27
    using CurrencyLibrary for Currency;
28
    using Hooks for IHooks;
29
    using LPFeeLibrary for uint24;
30

                            
                        
31
    uint160 internal constant MIN_PRICE_LIMIT = TickMath.MIN_SQRT_PRICE + 1;
32
    uint160 internal constant MAX_PRICE_LIMIT = TickMath.MAX_SQRT_PRICE - 1;
33

                            
                        
34
    address Harness;
35

                            
                        
36
    constructor(IPoolManager _manager) PoolTestBase(_manager) {
37
        Harness = msg.sender;
38
    }
39

                            
                        
40
    function proxyApprove(Currency token, address spender) public {
41
        MockERC20(Currency.unwrap(token)).approve(spender, type(uint256).max);
42
    }
43

                            
                        
44
    struct TestSettings {
45
        bool takeClaims;
46
        bool settleUsingBurn;
47
    }
48

                            
                        
49
    /// @custom:property After a swap, the actor's fromFunds should decrease or not change, and their toFunds should increase or not change.
50
    /// @custom:precondition PoolKey is an initialized pool.
51
    /// @custom:notes 
52
    function swapOneDirection(bool zeroForOne, int256 amount, PoolKey memory poolKey) public returns (SwapInfo memory) {
53
        Currency fromCurrency = zeroForOne ? poolKey.currency0 : poolKey.currency1;
54
        Currency toCurrency = zeroForOne ? poolKey.currency1 : poolKey.currency0;
55
        SwapInfo memory swap1Results = SwapInfoLibrary.initialize(fromCurrency, toCurrency, address(Harness));
56

                            
                        
57
        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
58
                zeroForOne: zeroForOne,
59
                amountSpecified: amount,
60
                sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT
61
            });
62
        TestSettings memory settings = TestSettings({takeClaims: false, settleUsingBurn: false});
63

                            
                        
64
        abi.decode(
65
            manager.unlock(abi.encode(CallbackData(address(this), settings, poolKey, params, new bytes(0)))), (BalanceDelta)
66
        );
67

                            
                        
68
        swap1Results.captureSwapResults();
69
        emit LogInt256("a Swap amount", amount);
70
        emit LogInt256("a Swap fromDelta", swap1Results.fromDelta);
71
        emit LogInt256("a Swap toDelta", swap1Results.toDelta);
72

                            
                        
73
        assertWithMsg(swap1Results.fromDelta <= 0, "fromDelta <= 0");
74
        assertWithMsg(swap1Results.toDelta >= 0, "toDelta >= 0");
75

                            
                        
76
        return swap1Results;
77
    }
78

                            
                        
79
    /// @custom:property After a bi-directional swap, the actor's fromFunds should decrease and their toFunds should decrease or not change.
80
    /// @custom:precondition PoolKey is an initialized pool.
81
    /// @custom:notes 
82
    function swapBiDirectional(bool zeroForOne, int256 amount, PoolKey memory poolKey) public {
83
        if(amount < 0){
84
            amount = amount * -1;
85
        }
86
        SwapInfo memory swap1Results = swapOneDirection(zeroForOne, amount, poolKey);
87

                            
                        
88
        // now swap in the opposite direction using the exact amount we received
89
        int256 newAmount = -1 * swap1Results.toDelta;
90
        require(newAmount != 0);
91

                            
                        
92
        SwapInfo memory swap2Results = swapOneDirection(!zeroForOne, newAmount, poolKey);
93

                            
                        
94
        // now actually verify the property
95
        int256 fromBalanceDifference = swap2Results.toBalanceAfter - swap1Results.fromBalanceBefore;
96
        int256 toBalanceDifference = swap2Results.fromBalanceAfter - swap1Results.toBalanceBefore;
97
        emit LogInt256("fromBalanceDifference", fromBalanceDifference);
98
        emit LogInt256("toBalanceDifference", toBalanceDifference);
99

                            
                        
100
        assertLt(fromBalanceDifference, 0, "Must not have more tokens than started with (from)");
101
        assertLte(toBalanceDifference, 0, "Must not have more tokens than started with (to)");
102
    }
103
    
104
    struct CallbackData {
105
        address sender;
106
        TestSettings testSettings;
107
        PoolKey key;
108
        IPoolManager.SwapParams params;
109
        bytes hookData;
110
    }
111

                            
                        
112
    function unlockCallback(bytes calldata rawData) external returns (bytes memory) {
113
        require(msg.sender == address(manager));
114
        CallbackData memory data = abi.decode(rawData, (CallbackData));
115

                            
                        
116
        (,, int256 deltaBefore0) = _fetchBalances(data.key.currency0, data.sender, address(this));
117
        (,, int256 deltaBefore1) = _fetchBalances(data.key.currency1, data.sender, address(this));
118

                            
                        
119
        assertWithMsg(deltaBefore0 == 0, "deltaBefore0 is not equal to 0");
120
        assertWithMsg(deltaBefore1 == 0, "deltaBefore1 is not equal to 0");
121

                            
                        
122
        BalanceDelta delta = manager.swap(data.key, data.params, data.hookData);
123

                            
                        
124
        (,, int256 deltaAfter0) = _fetchBalances(data.key.currency0, data.sender, address(this));
125
        (,, int256 deltaAfter1) = _fetchBalances(data.key.currency1, data.sender, address(this));
126

                            
                        
127
        if (data.params.zeroForOne) {
128
            if (data.params.amountSpecified < 0) {
129
                // exact input, 0 for 1
130
                assertWithMsg(
131
                    deltaAfter0 >= data.params.amountSpecified,
132
                    "deltaAfter0 is not greater than or equal to data.params.amountSpecified"
133
                );
134
                assertWithMsg(delta.amount0() == deltaAfter0, "delta.amount0() is not equal to deltaAfter0");
135
                assertWithMsg(deltaAfter1 >= 0, "deltaAfter1 is not greater than or equal to 0");
136
            } else {
137
                // exact output, 0 for 1
138
                assertWithMsg(deltaAfter0 <= 0, "deltaAfter0 is not less than or equal to zero");
139
                assertWithMsg(delta.amount1() == deltaAfter1, "delta.amount1() is not equal to deltaAfter1");
140
                assertWithMsg(
141
                    deltaAfter1 <= data.params.amountSpecified,
142
                    "deltaAfter1 is not less than or equal to data.params.amountSpecified"
143
                );
144
            }
145
        } else {
146
            if (data.params.amountSpecified < 0) {
147
                // exact input, 1 for 0
148
                assertWithMsg(
149
                    deltaAfter1 >= data.params.amountSpecified,
150
                    "deltaAfter1 is not greater than or equal to data.params.amountSpecified"
151
                );
152
                assertWithMsg(delta.amount1() == deltaAfter1, "delta.amount1() is not equal to deltaAfter1");
153
                assertWithMsg(deltaAfter0 >= 0, "deltaAfter0 is not greater than or equal to 0");
154
            } else {
155
                // exact output, 1 for 0
156
                assertWithMsg(deltaAfter1 <= 0, "deltaAfter1 is not less than or equal to 0");
157
                assertWithMsg(delta.amount0() == deltaAfter0, "delta.amount0() is not equal to deltaAfter0");
158
                assertWithMsg(
159
                    deltaAfter0 <= data.params.amountSpecified,
160
                    "deltaAfter0 is not less than or equal to data.params.amountSpecified"
161
                );
162
            }
163
        }
164

                            
                        
165

                            
                        
166
        if (deltaAfter0 < 0) {
167
            // obtain tokens from harness
168
            MockERC20(Currency.unwrap(data.key.currency0)).transferFrom(Harness, address(this), uint256(-deltaAfter0));
169
            CurrencySettler.settle(data.key.currency0, manager, data.sender, uint256(-deltaAfter0), false);
170
        }
171
        if (deltaAfter1 < 0) {
172
            // obtain tokens from harness
173
            MockERC20(Currency.unwrap(data.key.currency1)).transferFrom(Harness, address(this), uint256(-deltaAfter1));
174
            CurrencySettler.settle(data.key.currency1, manager, data.sender, uint256(-deltaAfter1), false);
175
        }
176
        if (deltaAfter0 > 0) {
177
            CurrencySettler.take(data.key.currency0, manager, data.sender, uint256(deltaAfter0), false);
178
            // send tokens back to harness
179
            data.key.currency0.transfer(Harness, uint256(deltaAfter0));
180
        }
181
        if (deltaAfter1 > 0) {
182
            CurrencySettler.take(data.key.currency1, manager, data.sender, uint256(deltaAfter1), false);
183
            // send tokens back to harness
184
            data.key.currency1.transfer( Harness, uint256(deltaAfter1));
185
        }
186

                            
                        
187
        return abi.encode(delta);
188
    }
189
}

Lines covered: 0 / 180 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.13;
3

                            
                        
4
import "forge-std/Test.sol";
5
import "forge-std/console2.sol";
6
import "test/trailofbits/ActionFuzzEntrypoint.sol";
7

                            
                        
8
import {Pool} from "src/libraries/Pool.sol";
9
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
10
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
11
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
12
import {PoolKey} from "src/types/PoolKey.sol";
13
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
14
import {StateLibrary} from "src/libraries/StateLibrary.sol";
15
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
16

                            
                        
17
/// @notice This test contract gives us a way to detect potential regressions in the Actions fuzzing harness and
18
/// explitily test regression sequences that were caused by false positives.
19
contract ActionsHarness_Test is Test {
20
    ActionFuzzEntrypoint target;
21
    using Pool for IPoolManager;
22
    using PoolIdLibrary for PoolKey;
23
    using TransientStateLibrary for IPoolManager;
24
    using StateLibrary for IPoolManager;
25

                            
                        
26
    function setUp() public {
27
        target = new ActionFuzzEntrypoint();
28
        payable(address(target)).transfer(address(this).balance - 20 ether);
29
        payable(address(target.getActionRouter())).transfer(20 ether);
30
    }
31

                            
                        
32
    function test_sync_test() public {
33
        target.addSync(uint8(0));
34
    }
35
    
36
    function test_initialize_and_add_liquidity_settle() public { 
37
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
38
        target.addSync(uint8(0));
39
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
40
        target.addSettle();
41
        target.addSync(uint8(1));
42
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
43
        target.addSettle();
44
        target.runActions();     
45
    }
46

                            
                        
47
    function test_initialize_and_add_liquidity_settle_for() public { 
48
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
49
        target.addSync(uint8(0));
50
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
51
        target.addSettleFor(address(target.getActionRouter()));
52
        target.addSync(uint8(1));
53
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
54
        target.addSettleFor(address(target.getActionRouter()));
55
        target.runActions();        
56
    }
57

                            
                        
58
    function test_donate() public {
59
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
60
        target.addSync(uint8(0));
61
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
62
        target.addSettleFor(address(target.getActionRouter()));
63
        target.addSync(uint8(1));
64
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
65
        target.addSettleFor(address(target.getActionRouter()));
66
        target.runActions(); 
67

                            
                        
68
        target.addDonate(0, 0.5 ether, 0.5 ether);
69
        target.addSync(uint8(0));
70
        target.addTransferFrom(0, 0.5 ether, address(target), address(target.getManager()));
71
        target.addSettle();
72
        target.addSync(uint8(1));
73
        target.addTransferFrom(1, 0.5 ether, address(target), address(target.getManager()));
74
        target.addSettle();
75
        target.runActions();
76
    }
77
    
78
    function test_take_settle() public {
79
        target.addSync(uint8(0));
80
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
81
        target.addSettleFor(address(target.getActionRouter()));
82
        target.addSync(uint8(0));
83
        target.addTake(0, 1 ether);
84
        target.runActions(); 
85

                            
                        
86
    }
87

                            
                        
88
    function test_swap() public {
89
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
90
        target.addSync(uint8(0));
91
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
92
        target.addSettleFor(address(target.getActionRouter()));
93
        target.addSync(uint8(1));
94
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
95
        target.addSettleFor(address(target.getActionRouter()));
96
        target.runActions(); 
97

                            
                        
98
        target.addSwap(0, -0.5 ether, true);
99
        target.addSync(uint8(0));
100
        target.addTransferFrom(0, 0.5 ether, address(target) , address(target.getManager()));
101
        target.addSettle();
102

                            
                        
103
        target.addSync(uint8(1));
104
        target.addTake(1, 333333333333333313);
105
        target.runActions(); 
106

                            
                        
107
    }
108

                            
                        
109
    function test_swap2() public {
110
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
111
        target.addSync(uint8(0));
112
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
113
        target.addSettleFor(address(target.getActionRouter()));
114
        target.addSync(uint8(1));
115
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
116
        target.addSettleFor(address(target.getActionRouter()));
117
        target.runActions(); 
118

                            
                        
119
        target.addSwap(0, -0.5 ether, false);
120
        target.addSync(uint8(1));
121
        target.addTransferFrom(1, 0.5 ether, address(target) , address(target.getManager()));
122
        target.addSettle();
123

                            
                        
124
        target.addSync(uint8(0));
125
        target.addTake(0, 333333333333333311);
126
        target.runActions(); 
127

                            
                        
128
    }
129

                            
                        
130
    function test_mint() public {
131
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
132
        target.addSync(uint8(0));
133
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
134
        target.addSettleFor(address(target.getActionRouter()));
135
        target.addSync(uint8(1));
136
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
137
        target.addSettleFor(address(target.getActionRouter()));
138
        target.runActions(); 
139

                            
                        
140
        target.addSwap(0, -0.5 ether, false);
141
        target.addSync(uint8(1));
142
        target.addTransferFrom(1, 0.5 ether, address(target) , address(target.getManager()));
143
        target.addSettle();
144

                            
                        
145
        target.addSync(uint8(0));
146
        target.addMint(address(target), 0, 333333333333333311);
147
        target.runActions(); 
148

                            
                        
149
    }
150

                            
                        
151
    function test_settle_native() public {
152
        uint8 nativeCurrencyIdx = uint8(target.NUMBER_CURRENCIES()-1);
153

                            
                        
154
        target.addInitializeAndAddLiquidity(0, nativeCurrencyIdx, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
155
        target.addSync(uint8(0));
156

                            
                        
157
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
158
        target.addSettleFor(address(target.getActionRouter()));
159

                            
                        
160
        target.addSync(uint8(nativeCurrencyIdx));
161
        target.addSettleNative(1 ether);
162
        target.runActions(); 
163

                            
                        
164
        target.addSwap(0, -0.5 ether, true);
165
        target.addSync(nativeCurrencyIdx);
166
        target.addSettleNative(0.5 ether);
167

                            
                        
168
        target.addSync(uint8(0));
169
        target.addTake(0, 333333333333333313);
170
        target.runActions(); 
171
    }
172

                            
                        
173
    function test_addShortcutSettle() public {
174
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
175
        target.addSync(uint8(0));
176
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
177
        target.addSettleFor(address(target.getActionRouter()));
178
        target.addSync(uint8(1));
179
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
180
        target.addSettleFor(address(target.getActionRouter()));
181
        target.runActions(); 
182

                            
                        
183
        target.addSwap(0, -0.5 ether, false);
184
        target.addShortcutSettle();
185
        target.runActions();
186
    }
187

                            
                        
188
    function test_burn() public {
189
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
190
        target.addSync(uint8(0));
191
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
192
        target.addSettleFor(address(target.getActionRouter()));
193
        target.addSync(uint8(1));
194
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
195
        target.addSettleFor(address(target.getActionRouter()));
196
        target.runActions(); 
197

                            
                        
198

                            
                        
199
        target.addSync(uint8(0));
200
        target.addMint(address(target.getActionRouter()), 0, 1 ether);
201
        target.addBurn(address(target.getActionRouter()), 0, 1 ether);
202
        
203
        target.addSettle();
204
        target.runActions(); 
205
    }
206

                            
                        
207
    function test_clear() public {
208
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
209
        target.addSync(uint8(0));
210
        target.addTransferFrom(0, 1 ether, address(target), address(target.getManager()));
211
        target.addSettleFor(address(target.getActionRouter()));
212
        target.addSync(uint8(1));
213
        target.addTransferFrom(1, 1 ether, address(target), address(target.getManager()));
214
        target.addSettleFor(address(target.getActionRouter()));
215
        target.runActions(); 
216

                            
                        
217
        target.addSwap(0, -0.5 ether, false);
218
        target.addSync(uint8(1));
219
        target.addTransferFrom(1, 0.5 ether, address(target) , address(target.getManager()));
220
        target.addSettle();
221

                            
                        
222
        target.addSync(uint8(0));
223
        target.addClear(0, 333333333333333311);
224
        target.runActions(); 
225
    }
226

                            
                        
227
    function test_swapin_out() public {
228
        target.addInitializeAndAddLiquidity(0, 1, 1, 79228162514264337593543950336, 0, -887272, 887272 , 1 ether, 0);
229
        target.addSwapInSwapOut(0, true, 1 ether);
230
        target.runActions();
231
    }
232

                            
                        
233
    function test_feegrowth_overflow() public {
234
        int128 amount = 1;
235
        target.addInitializeAndAddLiquidityAndSettle(0, 1, 1, 79228162514264337593543950336, 1_000_000, 0, 1 , amount, 0);
236
        PoolId poolId = abi.decode(hex"ad005400d48c3dc36756210997b5869d257ca207f4d5085e1bd29919092d6a97", (PoolId));
237
        (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = IPoolManager(target.getManager()).getFeeGrowthInside(poolId, 0, 1);
238
        
239
        for(uint i=0; i<3; i++) {
240
            console2.logUint(i);
241
            target.addDonate(0, uint128(type(int128).max), uint128(type(int128).max));
242
            target.addShortcutSettle();
243
            target.runActions();
244
        }
245

                            
                        
246
        (feeGrowthInside0X128, feeGrowthInside1X128) = IPoolManager(target.getManager()).getFeeGrowthInside(poolId, 0, 1);
247

                            
                        
248
        console2.logUint(feeGrowthInside0X128/FixedPoint128.Q128);
249
        console2.logUint(feeGrowthInside1X128/FixedPoint128.Q128);
250

                            
                        
251
    }
252

                            
                        
253
    function test_targeted_pool() public {
254
        target.addTargetedPoolReadyToOverflow(0, 1, 0);
255

                            
                        
256
    }
257

                            
                        
258
    function test_fee_miscalculation_regression() public {
259
        target.addTargetedPool(1,0,0,99);
260
        target.addModifyPositionAndRunActions(0,0,-1,934735867213017,13541478287070347540639706863682772478921284014365313132303827141936693186);
261
        target.addSetNewProtocolFee(0,1);
262
        target.addSwapAndRunActions(0,4110922,true);
263
    }
264

                            
                        
265
    function test_shadowaccounting_regression_1() public {
266
        target.addTargetedPool(0,3,0,273233);
267
        target.addModifyPositionAndRunActions(0,-2,0,248701260024546,1115970101497554417622751038604682045916585273685975242110649999204994190);
268
        target.addSetNewProtocolFee(0,1);
269
        target.addSwapAndRunActions(0,33216723,true);
270
    }
271

                            
                        
272
    function test_shadowaccounting_regression_2() public {
273
        target.addTargetedPool(1,0,0,1);
274
        target.addModifyPositionAndRunActions(0,-1001,-161,1478484426,115792089237316195423570985008687907853269984665640564039457584007913129637888);
275
        target.addSwapAndRunActions(0,1,true);
276
        target.addDonateAndSettle(0,2);
277
        target.addModifyPositionAndRunActions(0,-1001,-161,277295330,115792089237316195423570985008687907853269984665640564039457584007913129637888);
278
    }
279

                            
                        
280
    function test_shadowaccounting_regression_3() public {
281
        target.addTargetedPool(0,59,1,-335483349064151699904);
282
        target.addModifyPosition(35,0,17096,53,82970313381531717844305482713703611020253841721915);
283
        target.addSettleFor(address(0));
284
        target.addBurnAndRunActions(address(0),16,0);
285
    }
286

                            
                        
287
    function test_shadowaccounting_regression_4() public {
288
        target.addSync(0);
289
        vm.roll(block.number + 38894);
290
        target.runActions();
291
        vm.roll(block.number + 38894);
292
        target.addSettleFor(address(0));
293
        vm.roll(block.number + 38894);
294
        target.runActions();
295

                            
                        
296
    }
297

                            
                        
298
    function test_swap_through_fee_overflow_pool() public {
299
        target.addTargetedPoolReadyToOverflow(1,0,1);
300
        target.addModifyPosition(0,2,1,1,2367934173550170961037218246786631748697795);
301
        target.addSwap(0,-3,false);
302
        target.addDonateAndSettle(0,0);
303
    }
304
    
305

                            
                        
306
    function test_swap_through_fee_overflow_pool2() public {
307
        target.addTargetedPoolReadyToOverflow(1,0,1);
308
        target.addModifyPosition(0,0,1,2,2367934173550170961037218246786631748697795);
309
        target.addDonateAndSettle(5,5);
310
        target.addSwap(0,-3,false);
311
        target.addShortcutSettle();
312
        target.runActions();
313
    }
314

                            
                        
315
    function test_poolliquidity_regression_1() public {
316
        target.addTargetedPoolReadyToOverflow(247, 0, 6909592);
317
        target.addModifyPositionAndRunActions(0, -14, 2530466, 2812, 115792089237316195423570985008687907853269984665640564039457584007913129638913);
318
        target.addSwapAndRunActions(0, 92274097787679228392889020467702269147, false);
319
        target.addModifyPositionAndRunActions(0, -14, 2530466, 793, 115792089237316195423570985008687907853269984665640564039457584007913129638913);
320
    }
321

                            
                        
322
    function test_assert111() public {
323

                            
                        
324
    }
325

                            
                        
326
}
327

                            
                        
328
    

Lines covered: 0 / 50 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.13;
3

                            
                        
4
import "forge-std/Test.sol";
5
import "forge-std/console2.sol";
6
import "test/trailofbits/ActionFuzzEntrypoint.sol";
7
import "test/trailofbits/PropertiesHelper.sol";
8

                            
                        
9
import {Pool} from "src/libraries/Pool.sol";
10
import {IPoolManager} from "src/interfaces/IPoolManager.sol";
11
import {PoolId, PoolIdLibrary} from "src/types/PoolId.sol";
12
import {CurrencyLibrary, Currency} from "src/types/Currency.sol";
13
import {PoolKey} from "src/types/PoolKey.sol";
14
import {TransientStateLibrary} from "src/libraries/TransientStateLibrary.sol";
15
import {StateLibrary} from "src/libraries/StateLibrary.sol";
16
import {FixedPoint128} from "src/libraries/FixedPoint128.sol";
17

                            
                        
18
/// @notice This test contract gives us a way to detect potential regressions in the Actions fuzzing harness and
19
/// explitily test regression sequences that were caused by false positives.
20

                            
                        
21
contract Tmp is PropertiesAsserts {
22
    function assertGtInt(int256 a, int256 b, string memory reason) public {
23
        assertGt(a,b, reason);
24
    }
25

                            
                        
26
    function assertGteInt(int256 a, int256 b, string memory reason) public {
27
        assertGte(a,b, reason);
28
    }
29

                            
                        
30
    function assertLtInt(int256 a, int256 b, string memory reason) public {
31
        assertLt(a,b, reason);
32
    }
33

                            
                        
34
    function assertLteInt(int256 a, int256 b, string memory reason) public {
35
        assertLte(a,b, reason);
36
    }
37

                            
                        
38
    function assertGtUInt(uint256 a, uint256 b, string memory reason) public {
39
        assertGt(a,b, reason);
40
    }
41

                            
                        
42
    function assertGteUInt(uint256 a, uint256 b, string memory reason) public {
43
        assertGte(a,b, reason);
44
    }
45

                            
                        
46
    function assertLtUInt(uint256 a, uint256 b, string memory reason) public {
47
        assertLt(a,b, reason);
48
    }
49

                            
                        
50
    function assertLteUInt(uint256 a, uint256 b, string memory reason) public {
51
        assertLte(a,b, reason);
52
    }
53

                            
                        
54
}
55

                            
                        
56
contract Regression_Test is Test {
57
    ActionFuzzEntrypoint target;
58
    using Pool for IPoolManager;
59
    using PoolIdLibrary for PoolKey;
60
    using TransientStateLibrary for IPoolManager;
61
    using StateLibrary for IPoolManager;
62

                            
                        
63
    function setUp() public {
64
        target = new ActionFuzzEntrypoint();
65
        payable(address(target)).transfer(address(this).balance - 20 ether);
66
        payable(address(target.getActionRouter())).transfer(20 ether);
67
    }
68

                            
                        
69
    function _calcDiffInt256(int256 a, int256 b) internal returns (uint256) {
70
        if (b > a) {
71
            int256 tmp = a;
72
            a = b;
73
            b = tmp;
74
        }
75
        uint256 trueDiff;
76
        unchecked {
77
            int256 diff = a - b;
78
            if(diff >= 0) {
79
                emit LogString("non overflow path");
80
                trueDiff = uint256(diff);
81
            } else {
82
                emit LogString("overflow");
83
                a -= type(int256).max;
84
                emit LogInt256("a", a);
85
                emit LogInt256("b", b);
86
                emit LogUint256("diffpre", (uint256(a-b)));
87
                trueDiff = uint256(a - b) + uint256(type(int256).max);
88
            }
89
        }
90
        return trueDiff;
91
    }
92

                            
                        
93
    event LogUint256(string, uint256);
94
    event LogInt256(string, int256);
95
    event LogAddress(string, address);
96
    event LogString(string);
97
    event LogBytes(bytes);
98

                            
                        
99
    function test_int_differ() public {
100
        int256 a = type(int256).max;
101
        int256 b = type(int256).min;
102
        uint256 d = _calcDiffInt256(a,b);
103
        uint256 e = _calcDiffInt256(b,a);
104
        assert(d == e);
105
        emit LogUint256("diff", e);
106
        emit LogUint256("max",type(uint256).max);
107

                            
                        
108
        assert(d == type(uint256).max);
109
    }
110

                            
                        
111
    function test_int() public {
112
        Tmp t = new Tmp();
113
        int256 a = type(int256).max;
114
        int256 b = type(int256).min;
115
        t.assertGtInt(a,b, "test 1");
116
        t.assertGteInt(a,b, "test 2");
117

                            
                        
118
        t.assertLtInt(b,a, "test 3");
119
        t.assertLteInt(b,a, "test 4");
120
    }
121

                            
                        
122
    function test_uint() public {
123
        Tmp t = new Tmp();
124
        uint256 a = type(uint256).max;
125
        uint256 b = type(uint256).min;
126
        t.assertGtUInt(a,b, "test 1");
127
        t.assertGteUInt(a,b, "test 2");
128

                            
                        
129
        t.assertLtUInt(b,a, "test 3");
130
        t.assertLteUInt(b,a, "test 4");
131
    }
132

                            
                        
133
}
134

                            
                        
135
    

Lines covered: 0 / 68 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {BalanceDelta, toBalanceDelta} from "../../src/types/BalanceDelta.sol";
6

                            
                        
7
contract TestBalanceDelta is Test {
8
    function test_toBalanceDelta() public pure {
9
        BalanceDelta balanceDelta = toBalanceDelta(0, 0);
10
        assertEq(balanceDelta.amount0(), 0);
11
        assertEq(balanceDelta.amount1(), 0);
12

                            
                        
13
        balanceDelta = toBalanceDelta(0, 1);
14
        assertEq(balanceDelta.amount0(), 0);
15
        assertEq(balanceDelta.amount1(), 1);
16

                            
                        
17
        balanceDelta = toBalanceDelta(1, 0);
18
        assertEq(balanceDelta.amount0(), 1);
19
        assertEq(balanceDelta.amount1(), 0);
20

                            
                        
21
        balanceDelta = toBalanceDelta(type(int128).max, type(int128).max);
22
        assertEq(balanceDelta.amount0(), type(int128).max);
23
        assertEq(balanceDelta.amount1(), type(int128).max);
24

                            
                        
25
        balanceDelta = toBalanceDelta(type(int128).min, type(int128).min);
26
        assertEq(balanceDelta.amount0(), type(int128).min);
27
        assertEq(balanceDelta.amount1(), type(int128).min);
28
    }
29

                            
                        
30
    function test_fuzz_toBalanceDelta(int128 x, int128 y) public pure {
31
        BalanceDelta balanceDelta = toBalanceDelta(x, y);
32
        int256 expectedBD = int256(uint256(bytes32(abi.encodePacked(x, y))));
33
        assertEq(BalanceDelta.unwrap(balanceDelta), expectedBD);
34
    }
35

                            
                        
36
    function test_fuzz_amount0_amount1(int128 x, int128 y) public pure {
37
        BalanceDelta balanceDelta = toBalanceDelta(x, y);
38
        assertEq(balanceDelta.amount0(), x);
39
        assertEq(balanceDelta.amount1(), y);
40
    }
41

                            
                        
42
    function test_add() public pure {
43
        BalanceDelta balanceDelta = toBalanceDelta(0, 0) + toBalanceDelta(0, 0);
44
        assertEq(balanceDelta.amount0(), 0);
45
        assertEq(balanceDelta.amount1(), 0);
46

                            
                        
47
        balanceDelta = toBalanceDelta(-1000, 1000) + toBalanceDelta(1000, -1000);
48
        assertEq(balanceDelta.amount0(), 0);
49
        assertEq(balanceDelta.amount1(), 0);
50

                            
                        
51
        balanceDelta =
52
            toBalanceDelta(type(int128).min, type(int128).max) + toBalanceDelta(type(int128).max, type(int128).min);
53
        assertEq(balanceDelta.amount0(), -1);
54
        assertEq(balanceDelta.amount1(), -1);
55

                            
                        
56
        balanceDelta = toBalanceDelta(type(int128).max / 2 + 1, type(int128).max / 2 + 1)
57
            + toBalanceDelta(type(int128).max / 2, type(int128).max / 2);
58
        assertEq(balanceDelta.amount0(), type(int128).max);
59
        assertEq(balanceDelta.amount1(), type(int128).max);
60
    }
61

                            
                        
62
    function test_add_revertsOnOverflow() public {
63
        // should revert because type(int128).max + 1 is not possible
64
        vm.expectRevert();
65
        toBalanceDelta(type(int128).max, 0) + toBalanceDelta(1, 0);
66

                            
                        
67
        vm.expectRevert();
68
        toBalanceDelta(0, type(int128).max) + toBalanceDelta(0, 1);
69
    }
70

                            
                        
71
    function test_fuzz_add(int128 a, int128 b, int128 c, int128 d) public {
72
        int256 ac = int256(a) + c;
73
        int256 bd = int256(b) + d;
74

                            
                        
75
        // if the addition overflows it should revert
76
        if (ac != int128(ac) || bd != int128(bd)) {
77
            vm.expectRevert();
78
        }
79

                            
                        
80
        BalanceDelta balanceDelta = toBalanceDelta(a, b) + toBalanceDelta(c, d);
81
        assertEq(balanceDelta.amount0(), ac);
82
        assertEq(balanceDelta.amount1(), bd);
83
    }
84

                            
                        
85
    function test_sub() public pure {
86
        BalanceDelta balanceDelta = toBalanceDelta(0, 0) - toBalanceDelta(0, 0);
87
        assertEq(balanceDelta.amount0(), 0);
88
        assertEq(balanceDelta.amount1(), 0);
89

                            
                        
90
        balanceDelta = toBalanceDelta(-1000, 1000) - toBalanceDelta(1000, -1000);
91
        assertEq(balanceDelta.amount0(), -2000);
92
        assertEq(balanceDelta.amount1(), 2000);
93

                            
                        
94
        balanceDelta =
95
            toBalanceDelta(-1000, -1000) - toBalanceDelta(-(type(int128).min + 1000), -(type(int128).min + 1000));
96
        assertEq(balanceDelta.amount0(), type(int128).min);
97
        assertEq(balanceDelta.amount1(), type(int128).min);
98

                            
                        
99
        balanceDelta = toBalanceDelta(type(int128).min / 2, type(int128).min / 2)
100
            - toBalanceDelta(-(type(int128).min / 2), -(type(int128).min / 2));
101
        assertEq(balanceDelta.amount0(), type(int128).min);
102
        assertEq(balanceDelta.amount1(), type(int128).min);
103
    }
104

                            
                        
105
    function test_sub_revertsOnUnderflow() public {
106
        // should revert because type(int128).min - 1 is not possible
107
        vm.expectRevert();
108
        toBalanceDelta(type(int128).min, 0) - toBalanceDelta(1, 0);
109

                            
                        
110
        vm.expectRevert();
111
        toBalanceDelta(0, type(int128).min) - toBalanceDelta(0, 1);
112
    }
113

                            
                        
114
    function test_fuzz_sub(int128 a, int128 b, int128 c, int128 d) public {
115
        int256 ac = int256(a) - c;
116
        int256 bd = int256(b) - d;
117

                            
                        
118
        // if the subtraction underflows it should revert
119
        if (ac != int128(ac) || bd != int128(bd)) {
120
            vm.expectRevert();
121
        }
122

                            
                        
123
        BalanceDelta balanceDelta = toBalanceDelta(a, b) - toBalanceDelta(c, d);
124
        assertEq(balanceDelta.amount0(), ac);
125
        assertEq(balanceDelta.amount1(), bd);
126
    }
127

                            
                        
128
    function test_fuzz_eq(int128 a, int128 b, int128 c, int128 d) public pure {
129
        bool isEqual = (toBalanceDelta(a, b) == toBalanceDelta(c, d));
130
        if (a == c && b == d) assertTrue(isEqual);
131
        else assertFalse(isEqual);
132
    }
133

                            
                        
134
    function test_fuzz_neq(int128 a, int128 b, int128 c, int128 d) public pure {
135
        bool isNotEqual = (toBalanceDelta(a, b) != toBalanceDelta(c, d));
136
        if (a != c || b != d) assertTrue(isNotEqual);
137
        else assertFalse(isNotEqual);
138
    }
139
}
140

                            
                        

Lines covered: 0 / 66 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {stdError} from "forge-std/StdError.sol";
6
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
7
import {Currency, CurrencyLibrary} from "../../src/types/Currency.sol";
8
import {CurrencyTest} from "../../src/test/CurrencyTest.sol";
9
import {EmptyRevertContract} from "../../src/test/EmptyRevertContract.sol";
10

                            
                        
11
contract TestCurrency is Test {
12
    uint256 constant initialERC20Balance = 1000 ether;
13
    address constant otherAddress = address(1);
14

                            
                        
15
    Currency nativeCurrency;
16
    Currency erc20Currency;
17
    CurrencyTest currencyTest;
18

                            
                        
19
    function setUp() public {
20
        currencyTest = new CurrencyTest();
21
        vm.deal(address(currencyTest), 30 ether);
22
        nativeCurrency = Currency.wrap(address(0));
23
        MockERC20 token = new MockERC20("TestA", "A", 18);
24
        token.mint(address(currencyTest), initialERC20Balance);
25
        erc20Currency = Currency.wrap(address(token));
26
    }
27

                            
                        
28
    function test_fuzz_equals(address a, address b) public pure {
29
        assertEq(a == b, Currency.wrap(a) == Currency.wrap(b));
30
    }
31

                            
                        
32
    function test_fuzz_greaterThan(address a, address b) public pure {
33
        assertEq(a > b, Currency.wrap(a) > Currency.wrap(b));
34
    }
35

                            
                        
36
    function test_fuzz_lessThan(address a, address b) public pure {
37
        assertEq(a < b, Currency.wrap(a) < Currency.wrap(b));
38
    }
39

                            
                        
40
    function test_fuzz_greaterThanOrEqualTo(address a, address b) public pure {
41
        assertEq(a >= b, Currency.wrap(a) >= Currency.wrap(b));
42
    }
43

                            
                        
44
    function test_fuzz_balanceOfSelf_native(uint256 amount) public {
45
        uint256 balanceBefore = address(currencyTest).balance;
46
        amount = bound(amount, 0, balanceBefore);
47
        currencyTest.transfer(nativeCurrency, otherAddress, amount);
48
        assertEq(balanceBefore - amount, address(currencyTest).balance);
49
        assertEq(currencyTest.balanceOfSelf(nativeCurrency), address(currencyTest).balance);
50
    }
51

                            
                        
52
    function test_fuzz_balanceOfSelf_token(uint256 amount) public {
53
        amount = bound(amount, 0, initialERC20Balance);
54
        currencyTest.transfer(erc20Currency, otherAddress, amount);
55
        assertEq(currencyTest.balanceOfSelf(erc20Currency), initialERC20Balance - amount);
56
        assertEq(
57
            currencyTest.balanceOfSelf(erc20Currency),
58
            MockERC20(Currency.unwrap(erc20Currency)).balanceOf(address(currencyTest))
59
        );
60
    }
61

                            
                        
62
    function test_fuzz_balanceOf_native(uint256 amount) public {
63
        uint256 currencyBalanceBefore = address(currencyTest).balance;
64
        amount = bound(amount, 0, address(currencyTest).balance);
65
        currencyTest.transfer(nativeCurrency, otherAddress, amount);
66

                            
                        
67
        assertEq(otherAddress.balance, amount);
68
        assertEq(address(currencyTest).balance, currencyBalanceBefore - amount);
69
        assertEq(otherAddress.balance, currencyTest.balanceOf(nativeCurrency, otherAddress));
70
    }
71

                            
                        
72
    function test_fuzz_balanceOf_token(uint256 amount) public {
73
        amount = bound(amount, 0, initialERC20Balance);
74
        currencyTest.transfer(erc20Currency, otherAddress, amount);
75
        assertEq(currencyTest.balanceOf(erc20Currency, otherAddress), amount);
76
        assertEq(currencyTest.balanceOfSelf(erc20Currency), initialERC20Balance - amount);
77
        assertEq(
78
            MockERC20(Currency.unwrap(erc20Currency)).balanceOf(otherAddress),
79
            currencyTest.balanceOf(erc20Currency, otherAddress)
80
        );
81
    }
82

                            
                        
83
    function test_isNative_native_returnsTrue() public view {
84
        assertEq(currencyTest.isNative(nativeCurrency), true);
85
    }
86

                            
                        
87
    function test_isNative_token_returnsFalse() public view {
88
        assertEq(currencyTest.isNative(erc20Currency), false);
89
    }
90

                            
                        
91
    function test_fuzz_isNative(Currency currency) public view {
92
        assertEq(currencyTest.isNative(currency), (Currency.unwrap(currency) == address(0)));
93
    }
94

                            
                        
95
    function test_toId_nativeReturns0() public view {
96
        assertEq(currencyTest.toId(nativeCurrency), uint256(0));
97
    }
98

                            
                        
99
    function test_fuzz_toId_returnsCurrencyAsUint256(Currency currency) public view {
100
        assertEq(currencyTest.toId(currency), uint256(uint160(Currency.unwrap(currency))));
101
    }
102

                            
                        
103
    function test_fromId_0ReturnsNative() public view {
104
        assertEq(Currency.unwrap(currencyTest.fromId(0)), Currency.unwrap(nativeCurrency));
105
    }
106

                            
                        
107
    function test_fuzz_fromId_returnsUint256AsCurrency(uint256 id) public view {
108
        uint160 expectedCurrency = uint160(uint256(type(uint160).max) & id);
109
        assertEq(Currency.unwrap(currencyTest.fromId(id)), address(expectedCurrency));
110
    }
111

                            
                        
112
    function test_fuzz_fromId_toId_opposites(Currency currency) public view {
113
        assertEq(Currency.unwrap(currency), Currency.unwrap(currencyTest.fromId(currencyTest.toId(currency))));
114
    }
115

                            
                        
116
    function test_fuzz_toId_fromId_opposites(uint256 id) public view {
117
        assertEq(id & 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, currencyTest.toId(currencyTest.fromId(id)));
118
    }
119

                            
                        
120
    function test_transfer_noReturnData() public {
121
        // This contract reverts with no data
122
        EmptyRevertContract emptyRevertingToken = new EmptyRevertContract();
123
        // the token reverts with no data, so our custom error will be emitted instead
124
        vm.expectRevert(abi.encodeWithSelector(CurrencyLibrary.ERC20TransferFailed.selector, new bytes(0)));
125
        currencyTest.transfer(Currency.wrap(address(emptyRevertingToken)), otherAddress, 100);
126
    }
127

                            
                        
128
    function test_fuzz_transfer_native(uint256 amount) public {
129
        uint256 balanceBefore = otherAddress.balance;
130
        uint256 contractBalanceBefore = address(currencyTest).balance;
131

                            
                        
132
        if (amount <= contractBalanceBefore) {
133
            currencyTest.transfer(nativeCurrency, otherAddress, amount);
134
            assertEq(otherAddress.balance, balanceBefore + amount);
135
            assertEq(address(currencyTest).balance, contractBalanceBefore - amount);
136
        } else {
137
            vm.expectRevert(abi.encodeWithSelector(CurrencyLibrary.NativeTransferFailed.selector, new bytes(0)));
138
            currencyTest.transfer(nativeCurrency, otherAddress, amount);
139
            assertEq(otherAddress.balance, balanceBefore);
140
        }
141
    }
142

                            
                        
143
    function test_fuzz_transfer_token(uint256 amount) public {
144
        uint256 balanceBefore = currencyTest.balanceOf(erc20Currency, otherAddress);
145

                            
                        
146
        if (amount <= initialERC20Balance) {
147
            currencyTest.transfer(erc20Currency, otherAddress, amount);
148
            assertEq(currencyTest.balanceOf(erc20Currency, otherAddress), balanceBefore + amount);
149
            assertEq(
150
                MockERC20(Currency.unwrap(erc20Currency)).balanceOf(address(currencyTest)), initialERC20Balance - amount
151
            );
152
        } else {
153
            // the token reverts with an overflow error message, so this is bubbled up
154
            vm.expectRevert(
155
                abi.encodeWithSelector(CurrencyLibrary.ERC20TransferFailed.selector, stdError.arithmeticError)
156
            );
157
            currencyTest.transfer(erc20Currency, otherAddress, amount);
158
            assertEq(currencyTest.balanceOf(erc20Currency, otherAddress), balanceBefore);
159
        }
160
    }
161
}
162

                            
                        

Lines covered: 0 / 15 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Slot0, Slot0Library} from "../../src/types/Slot0.sol";
6

                            
                        
7
contract TestSlot0 is Test {
8
    function test_slot0_constants_masks() public pure {
9
        assertEq(Slot0Library.MASK_160_BITS, type(uint160).max);
10
        assertEq(Slot0Library.MASK_24_BITS, type(uint24).max);
11
    }
12

                            
                        
13
    function test_fuzz_slot0_pack_unpack(uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee)
14
        public
15
        pure
16
    {
17
        // pack starting from "lowest" field
18
        Slot0 _slot0 = Slot0.wrap(bytes32(0)).setSqrtPriceX96(sqrtPriceX96).setTick(tick).setProtocolFee(protocolFee)
19
            .setLpFee(lpFee);
20

                            
                        
21
        assertEq(_slot0.sqrtPriceX96(), sqrtPriceX96);
22
        assertEq(_slot0.tick(), tick);
23
        assertEq(_slot0.protocolFee(), protocolFee);
24
        assertEq(_slot0.lpFee(), lpFee);
25

                            
                        
26
        // pack starting from "highest" field
27
        _slot0 = Slot0.wrap(bytes32(0)).setLpFee(lpFee).setProtocolFee(protocolFee).setTick(tick).setSqrtPriceX96(
28
            sqrtPriceX96
29
        );
30

                            
                        
31
        assertEq(_slot0.sqrtPriceX96(), sqrtPriceX96);
32
        assertEq(_slot0.tick(), tick);
33
        assertEq(_slot0.protocolFee(), protocolFee);
34
        assertEq(_slot0.lpFee(), lpFee);
35
    }
36
}
37

                            
                        

Lines covered: 0 / 0 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {LiquidityAmounts} from "./LiquidityAmounts.sol";
5
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
6
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
7
import {TickMath} from "../../src/libraries/TickMath.sol";
8
import {PoolKey} from "../../src/types/PoolKey.sol";
9
import {StateLibrary} from "../../src/libraries/StateLibrary.sol";
10

                            
                        
11
/// @title Calculate token<>liquidity
12
/// @notice Helps calculate amounts for bounding fuzz tests
13
/*
14
library AmountHelpers {
15
    function getMaxAmountInForPool(
16
        IPoolManager manager,
17
        IPoolManager.ModifyLiquidityParams memory params,
18
        PoolKey memory key
19
    ) public view returns (uint256 amount0, uint256 amount1) {
20
        PoolId id = PoolIdLibrary.toId(key);
21
        uint128 liquidity = StateLibrary.getLiquidity(manager, id);
22
        (uint160 sqrtPriceX96,,,) = StateLibrary.getSlot0(manager, id);
23

                            
                        
24
        uint160 sqrtPriceX96Lower = TickMath.getSqrtPriceAtTick(params.tickLower);
25
        uint160 sqrtPriceX96Upper = TickMath.getSqrtPriceAtTick(params.tickUpper);
26

                            
                        
27
        amount0 = LiquidityAmounts.getAmount0ForLiquidity(sqrtPriceX96Lower, sqrtPriceX96, liquidity);
28
        amount1 = LiquidityAmounts.getAmount1ForLiquidity(sqrtPriceX96Upper, sqrtPriceX96, liquidity);
29
    }
30
}
31
*/
32

                            
                        

Lines covered: 1 / 13 (7.7%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
library Constants {
5
    uint160 public constant SQRT_PRICE_1_1 = 79228162514264337593543950336;
6
√ 1
    uint160 public constant SQRT_PRICE_1_2 = 56022770974786139918731938227;
7
    uint160 public constant SQRT_PRICE_1_4 = 39614081257132168796771975168;
8
    uint160 public constant SQRT_PRICE_2_1 = 112045541949572279837463876454;
9
    uint160 public constant SQRT_PRICE_4_1 = 158456325028528675187087900672;
10
    uint160 public constant SQRT_PRICE_121_100 = 87150978765690771352898345369;
11

                            
                        
12
    uint256 constant MAX_UINT256 = type(uint256).max;
13
    uint128 constant MAX_UINT128 = type(uint128).max;
14
    uint160 constant MAX_UINT160 = type(uint160).max;
15

                            
                        
16
    address constant ADDRESS_ZERO = address(0);
17

                            
                        
18
    /// 0011 1111 1111 1111
19
    address payable constant ALL_HOOKS = payable(0x0000000000000000000000000000000000003fFF);
20

                            
                        
21
    uint256 constant TICKS_OFFSET = 4;
22

                            
                        
23
    uint24 constant FEE_LOW = 500;
24
    uint24 constant FEE_MEDIUM = 3000;
25
    uint24 constant FEE_HIGH = 10000;
26

                            
                        
27
    bytes constant ZERO_BYTES = new bytes(0);
28
}
29

                            
                        

Lines covered: 0 / 11 (0.0%)

1
// SPDX-License-Identifier: MIT
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Currency} from "../../src/types/Currency.sol";
5
import {IERC20Minimal} from "../../src/interfaces/external/IERC20Minimal.sol";
6
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
7

                            
                        
8
/// @notice Library used to interact with PoolManager.sol to settle any open deltas.
9
/// To settle a positive delta (a credit to the user), a user may take or mint.
10
/// To settle a negative delta (a debt on the user), a user make transfer or burn to pay off a debt.
11
/// @dev Note that sync() is called before any erc-20 transfer in `settle`.
12
library CurrencySettler {
13
    /// @notice Settle (pay) a currency to the PoolManager
14
    /// @param currency Currency to settle
15
    /// @param manager IPoolManager to settle to
16
    /// @param payer Address of the payer, the token sender
17
    /// @param amount Amount to send
18
    /// @param burn If true, burn the ERC-6909 token, otherwise ERC20-transfer to the PoolManager
19
    function settle(Currency currency, IPoolManager manager, address payer, uint256 amount, bool burn) internal {
20
        // for native currencies or burns, calling sync is not required
21
        // short circuit for ERC-6909 burns to support ERC-6909-wrapped native tokens
22
        if (burn) {
23
            manager.burn(payer, currency.toId(), amount);
24
        } else if (currency.isNative()) {
25
            manager.settle{value: amount}();
26
        } else {
27
            manager.sync(currency);
28
            if (payer != address(this)) {
29
                IERC20Minimal(Currency.unwrap(currency)).transferFrom(payer, address(manager), amount);
30
            } else {
31
                IERC20Minimal(Currency.unwrap(currency)).transfer(address(manager), amount);
32
            }
33
            manager.settle();
34
        }
35
    }
36

                            
                        
37
    /// @notice Take (receive) a currency from the PoolManager
38
    /// @param currency Currency to take
39
    /// @param manager IPoolManager to take from
40
    /// @param recipient Address of the recipient, the token receiver
41
    /// @param amount Amount to receive
42
    /// @param claims If true, mint the ERC-6909 token, otherwise ERC20-transfer from the PoolManager to recipient
43
    function take(Currency currency, IPoolManager manager, address recipient, uint256 amount, bool claims) internal {
44
        claims ? manager.mint(recipient, currency.toId(), amount) : manager.take(currency, recipient, amount);
45
    }
46
}
47

                            
                        

Lines covered: 0 / 109 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
5
import {Hooks} from "../../src/libraries/Hooks.sol";
6
import {Currency, CurrencyLibrary} from "../../src/types/Currency.sol";
7
import {IHooks} from "../../src/interfaces/IHooks.sol";
8
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
9
import {PoolManager} from "../../src/PoolManager.sol";
10
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
11
import {LPFeeLibrary} from "../../src/libraries/LPFeeLibrary.sol";
12
import {PoolKey} from "../../src/types/PoolKey.sol";
13
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
14
import {TickMath} from "../../src/libraries/TickMath.sol";
15
import {Constants} from "../utils/Constants.sol";
16
import {SortTokens} from "./SortTokens.sol";
17
import {PoolModifyLiquidityTest} from "../../src/test/PoolModifyLiquidityTest.sol";
18
import {PoolModifyLiquidityTestNoChecks} from "../../src/test/PoolModifyLiquidityTestNoChecks.sol";
19
import {PoolSwapTest} from "../../src/test/PoolSwapTest.sol";
20
import {SwapRouterNoChecks} from "../../src/test/SwapRouterNoChecks.sol";
21
import {PoolDonateTest} from "../../src/test/PoolDonateTest.sol";
22
import {PoolNestedActionsTest} from "../../src/test/PoolNestedActionsTest.sol";
23
import {PoolTakeTest} from "../../src/test/PoolTakeTest.sol";
24
import {PoolSettleTest} from "../../src/test/PoolSettleTest.sol";
25
import {PoolClaimsTest} from "../../src/test/PoolClaimsTest.sol";
26
import {ActionsRouter} from "../../src/test/ActionsRouter.sol";
27
import {LiquidityAmounts} from "../../test/utils/LiquidityAmounts.sol";
28
import {StateLibrary} from "../../src/libraries/StateLibrary.sol";
29
import {
30
    ProtocolFeeControllerTest,
31
    OutOfBoundsProtocolFeeControllerTest,
32
    RevertingProtocolFeeControllerTest,
33
    OverflowProtocolFeeControllerTest,
34
    InvalidReturnSizeProtocolFeeControllerTest
35
} from "../../src/test/ProtocolFeeControllerTest.sol";
36

                            
                        
37
contract Deployers {
38
    using LPFeeLibrary for uint24;
39
    using PoolIdLibrary for PoolKey;
40
    using StateLibrary for IPoolManager;
41

                            
                        
42
    // Helpful test constants
43
    bytes constant ZERO_BYTES = Constants.ZERO_BYTES;
44
    uint160 constant SQRT_PRICE_1_1 = Constants.SQRT_PRICE_1_1;
45
    uint160 constant SQRT_PRICE_1_2 = Constants.SQRT_PRICE_1_2;
46
    uint160 constant SQRT_PRICE_2_1 = Constants.SQRT_PRICE_2_1;
47
    uint160 constant SQRT_PRICE_1_4 = Constants.SQRT_PRICE_1_4;
48
    uint160 constant SQRT_PRICE_4_1 = Constants.SQRT_PRICE_4_1;
49

                            
                        
50
    uint160 public constant MIN_PRICE_LIMIT = TickMath.MIN_SQRT_PRICE + 1;
51
    uint160 public constant MAX_PRICE_LIMIT = TickMath.MAX_SQRT_PRICE - 1;
52

                            
                        
53
    IPoolManager.ModifyLiquidityParams public LIQUIDITY_PARAMS =
54
        IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: 1e18, salt: 0});
55
    IPoolManager.ModifyLiquidityParams public REMOVE_LIQUIDITY_PARAMS =
56
        IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: -1e18, salt: 0});
57
    IPoolManager.SwapParams public SWAP_PARAMS =
58
        IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_PRICE_1_2});
59

                            
                        
60
    // Global variables
61
    Currency internal currency0;
62
    Currency internal currency1;
63
    IPoolManager manager;
64
    PoolModifyLiquidityTest modifyLiquidityRouter;
65
    PoolModifyLiquidityTestNoChecks modifyLiquidityNoChecks;
66
    SwapRouterNoChecks swapRouterNoChecks;
67
    PoolSwapTest swapRouter;
68
    PoolDonateTest donateRouter;
69
    PoolTakeTest takeRouter;
70
    PoolSettleTest settleRouter;
71
    ActionsRouter actionsRouter;
72

                            
                        
73
    PoolClaimsTest claimsRouter;
74
    PoolNestedActionsTest nestedActionRouter;
75
    ProtocolFeeControllerTest feeController;
76
    RevertingProtocolFeeControllerTest revertingFeeController;
77
    OutOfBoundsProtocolFeeControllerTest outOfBoundsFeeController;
78
    OverflowProtocolFeeControllerTest overflowFeeController;
79
    InvalidReturnSizeProtocolFeeControllerTest invalidReturnSizeFeeController;
80

                            
                        
81
    PoolKey key;
82
    PoolKey nativeKey;
83
    PoolKey uninitializedKey;
84
    PoolKey uninitializedNativeKey;
85

                            
                        
86
    // Update this value when you add a new hook flag.
87
    uint160 hookPermissionCount = 14;
88
    uint160 clearAllHookPermissionsMask = ~uint160(0) << (hookPermissionCount);
89

                            
                        
90
    modifier noIsolate() {
91
        if (msg.sender != address(this)) {
92
            (bool success,) = address(this).call(msg.data);
93
            require(success);
94
        } else {
95
            _;
96
        }
97
    }
98

                            
                        
99
    function deployFreshManager() internal virtual {
100
        manager = new PoolManager(500000);
101
    }
102

                            
                        
103
    function deployFreshManagerAndRouters() internal {
104
        deployFreshManager();
105
        swapRouter = new PoolSwapTest(manager);
106
        swapRouterNoChecks = new SwapRouterNoChecks(manager);
107
        modifyLiquidityRouter = new PoolModifyLiquidityTest(manager);
108
        modifyLiquidityNoChecks = new PoolModifyLiquidityTestNoChecks(manager);
109
        donateRouter = new PoolDonateTest(manager);
110
        takeRouter = new PoolTakeTest(manager);
111
        settleRouter = new PoolSettleTest(manager);
112
        claimsRouter = new PoolClaimsTest(manager);
113
        nestedActionRouter = new PoolNestedActionsTest(manager);
114
        feeController = new ProtocolFeeControllerTest();
115
        revertingFeeController = new RevertingProtocolFeeControllerTest();
116
        outOfBoundsFeeController = new OutOfBoundsProtocolFeeControllerTest();
117
        overflowFeeController = new OverflowProtocolFeeControllerTest();
118
        invalidReturnSizeFeeController = new InvalidReturnSizeProtocolFeeControllerTest();
119
        actionsRouter = new ActionsRouter(manager);
120

                            
                        
121
        manager.setProtocolFeeController(feeController);
122
    }
123

                            
                        
124
    // You must have first initialised the routers with deployFreshManagerAndRouters
125
    // If you only need the currencies (and not approvals) call deployAndMint2Currencies
126
    function deployMintAndApprove2Currencies() internal returns (Currency, Currency) {
127
        Currency _currencyA = deployMintAndApproveCurrency();
128
        Currency _currencyB = deployMintAndApproveCurrency();
129

                            
                        
130
        (currency0, currency1) =
131
            SortTokens.sort(MockERC20(Currency.unwrap(_currencyA)), MockERC20(Currency.unwrap(_currencyB)));
132
        return (currency0, currency1);
133
    }
134

                            
                        
135
    function deployMintAndApproveCurrency() internal returns (Currency currency) {
136
        MockERC20 token = deployTokens(1, 2 ** 255)[0];
137

                            
                        
138
        address[9] memory toApprove = [
139
            address(swapRouter),
140
            address(swapRouterNoChecks),
141
            address(modifyLiquidityRouter),
142
            address(modifyLiquidityNoChecks),
143
            address(donateRouter),
144
            address(takeRouter),
145
            address(claimsRouter),
146
            address(nestedActionRouter.executor()),
147
            address(actionsRouter)
148
        ];
149

                            
                        
150
        for (uint256 i = 0; i < toApprove.length; i++) {
151
            token.approve(toApprove[i], Constants.MAX_UINT256);
152
        }
153

                            
                        
154
        return Currency.wrap(address(token));
155
    }
156

                            
                        
157
    function deployAndMint2Currencies() internal returns (Currency, Currency) {
158
        MockERC20[] memory tokens = deployTokens(2, 2 ** 255);
159
        return SortTokens.sort(tokens[0], tokens[1]);
160
    }
161

                            
                        
162
    function deployTokens(uint8 count, uint256 totalSupply) internal returns (MockERC20[] memory tokens) {
163
        tokens = new MockERC20[](count);
164
        for (uint8 i = 0; i < count; i++) {
165
            tokens[i] = new MockERC20("TEST", "TEST", 18);
166
            tokens[i].mint(address(this), totalSupply);
167
        }
168
    }
169

                            
                        
170
    function initPool(
171
        Currency _currency0,
172
        Currency _currency1,
173
        IHooks hooks,
174
        uint24 fee,
175
        uint160 sqrtPriceX96,
176
        bytes memory initData
177
    ) internal returns (PoolKey memory _key, PoolId id) {
178
        _key = PoolKey(_currency0, _currency1, fee, fee.isDynamicFee() ? int24(60) : int24(fee / 100 * 2), hooks);
179
        id = _key.toId();
180
        manager.initialize(_key, sqrtPriceX96, initData);
181
    }
182

                            
                        
183
    function initPool(
184
        Currency _currency0,
185
        Currency _currency1,
186
        IHooks hooks,
187
        uint24 fee,
188
        int24 tickSpacing,
189
        uint160 sqrtPriceX96,
190
        bytes memory initData
191
    ) internal returns (PoolKey memory _key, PoolId id) {
192
        _key = PoolKey(_currency0, _currency1, fee, tickSpacing, hooks);
193
        id = _key.toId();
194
        manager.initialize(_key, sqrtPriceX96, initData);
195
    }
196

                            
                        
197
    function initPoolAndAddLiquidity(
198
        Currency _currency0,
199
        Currency _currency1,
200
        IHooks hooks,
201
        uint24 fee,
202
        uint160 sqrtPriceX96,
203
        bytes memory initData
204
    ) internal returns (PoolKey memory _key, PoolId id) {
205
        (_key, id) = initPool(_currency0, _currency1, hooks, fee, sqrtPriceX96, initData);
206
        modifyLiquidityRouter.modifyLiquidity{value: msg.value}(_key, LIQUIDITY_PARAMS, ZERO_BYTES);
207
    }
208

                            
                        
209
    function initPoolAndAddLiquidityETH(
210
        Currency _currency0,
211
        Currency _currency1,
212
        IHooks hooks,
213
        uint24 fee,
214
        uint160 sqrtPriceX96,
215
        bytes memory initData,
216
        uint256 msgValue
217
    ) internal returns (PoolKey memory _key, PoolId id) {
218
        (_key, id) = initPool(_currency0, _currency1, hooks, fee, sqrtPriceX96, initData);
219
        modifyLiquidityRouter.modifyLiquidity{value: msgValue}(_key, LIQUIDITY_PARAMS, ZERO_BYTES);
220
    }
221

                            
                        
222
    // Deploys the manager, all test routers, and sets up 2 pools: with and without native
223
    function initializeManagerRoutersAndPoolsWithLiq(IHooks hooks) internal {
224
        deployFreshManagerAndRouters();
225
        // sets the global currencies and key
226
        deployMintAndApprove2Currencies();
227
        (key,) = initPoolAndAddLiquidity(currency0, currency1, hooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES);
228
        nestedActionRouter.executor().setKey(key);
229
        (nativeKey,) = initPoolAndAddLiquidityETH(
230
            CurrencyLibrary.NATIVE, currency1, hooks, 3000, SQRT_PRICE_1_1, ZERO_BYTES, 1 ether
231
        );
232
        uninitializedKey = key;
233
        uninitializedNativeKey = nativeKey;
234
        uninitializedKey.fee = 100;
235
        uninitializedNativeKey.fee = 100;
236
    }
237

                            
                        
238
    /// @notice Helper function for a simple ERC20 swaps that allows for unlimited price impact
239
    function swap(PoolKey memory _key, bool zeroForOne, int256 amountSpecified, bytes memory hookData)
240
        internal
241
        returns (BalanceDelta)
242
    {
243
        // allow native input for exact-input, guide users to the `swapNativeInput` function
244
        bool isNativeInput = zeroForOne && _key.currency0.isNative();
245
        if (isNativeInput) require(0 > amountSpecified, "Use swapNativeInput() for native-token exact-output swaps");
246

                            
                        
247
        uint256 value = isNativeInput ? uint256(-amountSpecified) : 0;
248

                            
                        
249
        return swapRouter.swap{value: value}(
250
            _key,
251
            IPoolManager.SwapParams({
252
                zeroForOne: zeroForOne,
253
                amountSpecified: amountSpecified,
254
                sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT
255
            }),
256
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}),
257
            hookData
258
        );
259
    }
260

                            
                        
261
    /// @notice Helper function to increase balance of pool manager.
262
    /// Uses default LIQUIDITY_PARAMS range.
263
    function seedMoreLiquidity(PoolKey memory _key, uint256 amount0, uint256 amount1) internal {
264
        (uint160 sqrtPriceX96,,,) = manager.getSlot0(_key.toId());
265
        uint128 liquidityDelta = LiquidityAmounts.getLiquidityForAmounts(
266
            sqrtPriceX96,
267
            TickMath.getSqrtPriceAtTick(LIQUIDITY_PARAMS.tickLower),
268
            TickMath.getSqrtPriceAtTick(LIQUIDITY_PARAMS.tickUpper),
269
            amount0,
270
            amount1
271
        );
272

                            
                        
273
        IPoolManager.ModifyLiquidityParams memory params = IPoolManager.ModifyLiquidityParams({
274
            tickLower: LIQUIDITY_PARAMS.tickLower,
275
            tickUpper: LIQUIDITY_PARAMS.tickUpper,
276
            liquidityDelta: int128(liquidityDelta),
277
            salt: 0
278
        });
279

                            
                        
280
        modifyLiquidityRouter.modifyLiquidity(_key, params, ZERO_BYTES);
281
    }
282

                            
                        
283
    /// @notice Helper function for a simple Native-token swap that allows for unlimited price impact
284
    function swapNativeInput(
285
        PoolKey memory _key,
286
        bool zeroForOne,
287
        int256 amountSpecified,
288
        bytes memory hookData,
289
        uint256 msgValue
290
    ) internal returns (BalanceDelta) {
291
        require(_key.currency0.isNative(), "currency0 is not native. Use swap() instead");
292
        if (zeroForOne == false) require(msgValue == 0, "msgValue must be 0 for oneForZero swaps");
293

                            
                        
294
        return swapRouter.swap{value: msgValue}(
295
            _key,
296
            IPoolManager.SwapParams({
297
                zeroForOne: zeroForOne,
298
                amountSpecified: amountSpecified,
299
                sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT
300
            }),
301
            PoolSwapTest.TestSettings({takeClaims: false, settleUsingBurn: false}),
302
            hookData
303
        );
304
    }
305

                            
                        
306
    // to receive refunds of spare eth from test helpers
307
    receive() external payable {}
308
}
309

                            
                        

Lines covered: 0 / 11 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {CommonBase} from "forge-std/Base.sol";
5

                            
                        
6
abstract contract JavascriptFfi is CommonBase {
7
    function runScript(string memory scriptName, string memory args) internal returns (bytes memory result) {
8
        string[] memory inputs = new string[](8);
9

                            
                        
10
        // build ffi command string
11
        inputs[0] = "npm";
12
        inputs[1] = "--silent";
13
        inputs[2] = "--prefix";
14
        inputs[3] = "./test/js-scripts";
15
        inputs[4] = "run";
16
        inputs[5] = scriptName;
17
        inputs[6] = "--";
18
        inputs[7] = args;
19
        result = vm.ffi(inputs);
20
    }
21
}
22

                            
                        

Lines covered: 0 / 34 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import "../../src/libraries/FullMath.sol";
5
import "../../src/libraries/FixedPoint96.sol";
6

                            
                        
7
/// @title Liquidity amount functions
8
/// @notice Provides functions for computing liquidity amounts from token amounts and prices
9
library LiquidityAmounts {
10
    /// @notice Downcasts uint256 to uint128
11
    /// @param x The uint258 to be downcasted
12
    /// @return y The passed value, downcasted to uint128
13
    function toUint128(uint256 x) private pure returns (uint128 y) {
14
        require((y = uint128(x)) == x, "liquidity overflow");
15
    }
16

                            
                        
17
    /// @notice Computes the amount of liquidity received for a given amount of token0 and price range
18
    /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))
19
    /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary
20
    /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary
21
    /// @param amount0 The amount0 being sent in
22
    /// @return liquidity The amount of returned liquidity
23
    function getLiquidityForAmount0(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount0)
24
        internal
25
        pure
26
        returns (uint128 liquidity)
27
    {
28
        if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
29
        uint256 intermediate = FullMath.mulDiv(sqrtPriceAX96, sqrtPriceBX96, FixedPoint96.Q96);
30
        return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtPriceBX96 - sqrtPriceAX96));
31
    }
32

                            
                        
33
    /// @notice Computes the amount of liquidity received for a given amount of token1 and price range
34
    /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).
35
    /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary
36
    /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary
37
    /// @param amount1 The amount1 being sent in
38
    /// @return liquidity The amount of returned liquidity
39
    function getLiquidityForAmount1(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount1)
40
        internal
41
        pure
42
        returns (uint128 liquidity)
43
    {
44
        if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
45
        return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtPriceBX96 - sqrtPriceAX96));
46
    }
47

                            
                        
48
    /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current
49
    /// pool prices and the prices at the tick boundaries
50
    /// @param sqrtPriceX96 A sqrt price representing the current pool prices
51
    /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary
52
    /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary
53
    /// @param amount0 The amount of token0 being sent in
54
    /// @param amount1 The amount of token1 being sent in
55
    /// @return liquidity The maximum amount of liquidity received
56
    function getLiquidityForAmounts(
57
        uint160 sqrtPriceX96,
58
        uint160 sqrtPriceAX96,
59
        uint160 sqrtPriceBX96,
60
        uint256 amount0,
61
        uint256 amount1
62
    ) internal pure returns (uint128 liquidity) {
63
        if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
64

                            
                        
65
        if (sqrtPriceX96 <= sqrtPriceAX96) {
66
            liquidity = getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0);
67
        } else if (sqrtPriceX96 < sqrtPriceBX96) {
68
            uint128 liquidity0 = getLiquidityForAmount0(sqrtPriceX96, sqrtPriceBX96, amount0);
69
            uint128 liquidity1 = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceX96, amount1);
70

                            
                        
71
            liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;
72
        } else {
73
            liquidity = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount1);
74
        }
75
    }
76

                            
                        
77
    /// @notice Computes the amount of token0 for a given amount of liquidity and a price range
78
    /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary
79
    /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary
80
    /// @param liquidity The liquidity being valued
81
    /// @return amount0 The amount of token0
82
    function getAmount0ForLiquidity(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity)
83
        internal
84
        pure
85
        returns (uint256 amount0)
86
    {
87
        if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
88

                            
                        
89
        return FullMath.mulDiv(
90
            uint256(liquidity) << FixedPoint96.RESOLUTION, sqrtPriceBX96 - sqrtPriceAX96, sqrtPriceBX96
91
        ) / sqrtPriceAX96;
92
    }
93

                            
                        
94
    /// @notice Computes the amount of token1 for a given amount of liquidity and a price range
95
    /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary
96
    /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary
97
    /// @param liquidity The liquidity being valued
98
    /// @return amount1 The amount of token1
99
    function getAmount1ForLiquidity(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity)
100
        internal
101
        pure
102
        returns (uint256 amount1)
103
    {
104
        if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
105

                            
                        
106
        return FullMath.mulDiv(liquidity, sqrtPriceBX96 - sqrtPriceAX96, FixedPoint96.Q96);
107
    }
108

                            
                        
109
    /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current
110
    /// pool prices and the prices at the tick boundaries
111
    /// @param sqrtPriceX96 A sqrt price representing the current pool prices
112
    /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary
113
    /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary
114
    /// @param liquidity The liquidity being valued
115
    /// @return amount0 The amount of token0
116
    /// @return amount1 The amount of token1
117
    function getAmountsForLiquidity(
118
        uint160 sqrtPriceX96,
119
        uint160 sqrtPriceAX96,
120
        uint160 sqrtPriceBX96,
121
        uint128 liquidity
122
    ) internal pure returns (uint256 amount0, uint256 amount1) {
123
        if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);
124

                            
                        
125
        if (sqrtPriceX96 <= sqrtPriceAX96) {
126
            amount0 = getAmount0ForLiquidity(sqrtPriceAX96, sqrtPriceBX96, liquidity);
127
        } else if (sqrtPriceX96 < sqrtPriceBX96) {
128
            amount0 = getAmount0ForLiquidity(sqrtPriceX96, sqrtPriceBX96, liquidity);
129
            amount1 = getAmount1ForLiquidity(sqrtPriceAX96, sqrtPriceX96, liquidity);
130
        } else {
131
            amount1 = getAmount1ForLiquidity(sqrtPriceAX96, sqrtPriceBX96, liquidity);
132
        }
133
    }
134
}
135

                            
                        

Lines covered: 0 / 6 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
5

                            
                        
6
import "forge-std/console2.sol";
7

                            
                        
8
// Useful for printing out the true values in a fuzz. For failing fuzzes, foundry logs the unsanitized params.
9
contract Logger {
10
    function logParams(IPoolManager.ModifyLiquidityParams memory params) public pure {
11
        console2.log("ModifyLiquidity.tickLower", params.tickLower);
12
        console2.log("ModifyLiquidity.tickUpper", params.tickUpper);
13
        console2.log("ModifyLiquidity.liquidityDelta", params.liquidityDelta);
14
        console2.log("ModifyLiquidity.salt");
15
        console2.logBytes32(params.salt);
16
    }
17
}
18

                            
                        

Lines covered: 0 / 8 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {Test} from "forge-std/Test.sol";
5
import {Deployers} from "test/utils/Deployers.sol";
6
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
7
import {Action} from "src/test/PoolNestedActionsTest.sol";
8
import {IHooks} from "src/interfaces/IHooks.sol";
9

                            
                        
10
contract NestedActions is Test, Deployers, GasSnapshot {
11
    Action[] actions;
12

                            
                        
13
    function setUp() public {
14
        initializeManagerRoutersAndPoolsWithLiq(IHooks(address(0)));
15
    }
16

                            
                        
17
    // Asserts and expected outcomes are tested inside the nestedActionRouter
18

                            
                        
19
    function test_nestedSwap() public {
20
        actions = [Action.SWAP_AND_SETTLE];
21
        nestedActionRouter.unlock(abi.encode(actions));
22
    }
23

                            
                        
24
    function test_nestedAddLiquidity() public {
25
        actions = [Action.ADD_LIQUIDITY_AND_SETTLE];
26
        nestedActionRouter.unlock(abi.encode(actions));
27
    }
28

                            
                        
29
    function test_nestedRemoveLiquidity() public {
30
        actions = [Action.ADD_LIQUIDITY_AND_SETTLE, Action.REMOVE_LIQUIDITY_AND_SETTLE];
31
        nestedActionRouter.unlock(abi.encode(actions));
32
    }
33

                            
                        
34
    function test_nestedDonate() public {
35
        actions = [Action.DONATE_AND_SETTLE];
36
        nestedActionRouter.unlock(abi.encode(actions));
37
    }
38

                            
                        
39
    function test_nestedInitialize() public {
40
        actions = [Action.INITIALIZE];
41
        nestedActionRouter.unlock(abi.encode(actions));
42
    }
43
}
44

                            
                        

Lines covered: 0 / 5 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
5
import {Currency} from "../../src/types/Currency.sol";
6

                            
                        
7
library SortTokens {
8
    function sort(MockERC20 tokenA, MockERC20 tokenB)
9
        internal
10
        pure
11
        returns (Currency _currency0, Currency _currency1)
12
    {
13
        if (address(tokenA) < address(tokenB)) {
14
            (_currency0, _currency1) = (Currency.wrap(address(tokenA)), Currency.wrap(address(tokenB)));
15
        } else {
16
            (_currency0, _currency1) = (Currency.wrap(address(tokenB)), Currency.wrap(address(tokenA)));
17
        }
18
    }
19
}
20

                            
                        

Lines covered: 0 / 42 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.20;
3

                            
                        
4
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
5
import {Test} from "forge-std/Test.sol";
6
import {Vm} from "forge-std/Vm.sol";
7
import {Hooks} from "../../src/libraries/Hooks.sol";
8
import {MockHooks} from "../../src/test/MockHooks.sol";
9
import {IPoolManager} from "../../src/interfaces/IPoolManager.sol";
10
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
11
import {IHooks} from "../../src/interfaces/IHooks.sol";
12
import {Currency} from "../../src/types/Currency.sol";
13
import {PoolManager} from "../../src/PoolManager.sol";
14
import {PoolSwapTest} from "../../src/test/PoolSwapTest.sol";
15
import {PoolDonateTest} from "../../src/test/PoolDonateTest.sol";
16
import {Deployers} from "./Deployers.sol";
17
import {ProtocolFees} from "../../src/ProtocolFees.sol";
18
import {PoolId, PoolIdLibrary} from "../../src/types/PoolId.sol";
19
import {PoolKey} from "../../src/types/PoolKey.sol";
20
import {IERC20Minimal} from "../../src/interfaces/external/IERC20Minimal.sol";
21
import {BalanceDelta} from "../../src/types/BalanceDelta.sol";
22
import {Constants} from "../utils/Constants.sol";
23

                            
                        
24
/// @notice Testing Deployers.swap() and Deployers.swapNativeInput()
25
contract SwapHelperTest is Test, Deployers, GasSnapshot {
26
    using PoolIdLibrary for PoolKey;
27
    using Hooks for IHooks;
28

                            
                        
29
    MockHooks mockHooks;
30

                            
                        
31
    function setUp() public {
32
        MockHooks impl = new MockHooks();
33
        vm.etch(Constants.ALL_HOOKS, address(impl).code);
34
        mockHooks = MockHooks(Constants.ALL_HOOKS);
35

                            
                        
36
        initializeManagerRoutersAndPoolsWithLiq(mockHooks);
37
    }
38

                            
                        
39
    // --- Deployers.swap() tests --- //
40
    function test_swap_helper_zeroForOne_exactInput() public {
41
        int256 amountSpecified = -100;
42
        BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
43
        assertEq(result.amount0(), amountSpecified);
44
    }
45

                            
                        
46
    function test_swap_helper_zeroForOne_exactOutput() public {
47
        int256 amountSpecified = 100;
48
        BalanceDelta result = swap(key, true, amountSpecified, ZERO_BYTES);
49
        assertEq(result.amount1(), amountSpecified);
50
    }
51

                            
                        
52
    function test_swap_helper_oneForZero_exactInput() public {
53
        int256 amountSpecified = -100;
54
        BalanceDelta result = swap(key, false, amountSpecified, ZERO_BYTES);
55
        assertEq(result.amount1(), amountSpecified);
56
    }
57

                            
                        
58
    function test_swap_helper_oneForZero_exactOutput() public {
59
        int256 amountSpecified = 100;
60
        BalanceDelta result = swap(key, false, amountSpecified, ZERO_BYTES);
61
        assertEq(result.amount0(), amountSpecified);
62
    }
63

                            
                        
64
    function test_swap_helper_native_zeroForOne_exactInput() public {
65
        int256 amountSpecified = -100;
66
        BalanceDelta result = swap(nativeKey, true, amountSpecified, ZERO_BYTES);
67
        assertEq(result.amount0(), amountSpecified);
68
    }
69

                            
                        
70
    function test_swap_helper_native_zeroForOne_exactOutput() public {
71
        int256 amountSpecified = 100;
72
        vm.expectRevert();
73
        swap(nativeKey, true, amountSpecified, ZERO_BYTES);
74
    }
75

                            
                        
76
    function test_swap_helper_native_oneForZero_exactInput() public {
77
        int256 amountSpecified = -100;
78
        BalanceDelta result = swap(nativeKey, false, amountSpecified, ZERO_BYTES);
79
        assertEq(result.amount1(), amountSpecified);
80
    }
81

                            
                        
82
    function test_swap_helper_native_oneForZero_exactOutput() public {
83
        int256 amountSpecified = 100;
84
        BalanceDelta result = swap(nativeKey, false, amountSpecified, ZERO_BYTES);
85
        assertEq(result.amount0(), amountSpecified);
86
    }
87

                            
                        
88
    // --- Deployers.swapNativeInput() tests --- //
89
    function test_swapNativeInput_helper_zeroForOne_exactInput() public {
90
        int256 amountSpecified = -100;
91
        BalanceDelta result = swapNativeInput(nativeKey, true, amountSpecified, ZERO_BYTES, 100 wei);
92
        assertEq(result.amount0(), amountSpecified);
93
    }
94

                            
                        
95
    function test_swapNativeInput_helper_zeroForOne_exactOutput() public {
96
        int256 amountSpecified = 100;
97
        BalanceDelta result = swapNativeInput(nativeKey, true, amountSpecified, ZERO_BYTES, 200 wei); // overpay
98
        assertEq(result.amount1(), amountSpecified);
99
    }
100

                            
                        
101
    function test_swapNativeInput_helper_oneForZero_exactInput() public {
102
        int256 amountSpecified = -100;
103
        BalanceDelta result = swapNativeInput(nativeKey, false, amountSpecified, ZERO_BYTES, 0 wei);
104
        assertEq(result.amount1(), amountSpecified);
105
    }
106

                            
                        
107
    function test_swapNativeInput_helper_oneForZero_exactOutput() public {
108
        int256 amountSpecified = 100;
109
        BalanceDelta result = swapNativeInput(nativeKey, false, amountSpecified, ZERO_BYTES, 0 wei);
110
        assertEq(result.amount0(), amountSpecified);
111
    }
112

                            
                        
113
    function test_swapNativeInput_helper_nonnative_zeroForOne_exactInput() public {
114
        int256 amountSpecified = -100;
115
        vm.expectRevert();
116
        swapNativeInput(key, true, amountSpecified, ZERO_BYTES, 0 wei);
117
    }
118

                            
                        
119
    function test_swapNativeInput_helper_nonnative_zeroForOne_exactOutput() public {
120
        int256 amountSpecified = 100;
121
        vm.expectRevert();
122
        swapNativeInput(key, true, amountSpecified, ZERO_BYTES, 0 wei);
123
    }
124

                            
                        
125
    function test_swapNativeInput_helper_nonnative_oneForZero_exactInput() public {
126
        int256 amountSpecified = -100;
127
        vm.expectRevert();
128
        swapNativeInput(key, false, amountSpecified, ZERO_BYTES, 0 wei);
129
    }
130

                            
                        
131
    function test_swapNativeInput_helper_nonnative_oneForZero_exactOutput() public {
132
        int256 amountSpecified = 100;
133
        vm.expectRevert();
134
        swapNativeInput(key, false, amountSpecified, ZERO_BYTES, 0 wei);
135
    }
136
}
137

                            
                        

Lines covered: 0 / 4 (0.0%)

1
// SPDX-License-Identifier: UNLICENSED
2
pragma solidity ^0.8.24;
3

                            
                        
4
import "forge-std/Test.sol";
5

                            
                        
6
interface IUniswapV3Factory {
7
    function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool);
8
    function enableFeeAmount(uint24 fee, int24 tickSpacing) external;
9
}
10

                            
                        
11
interface IUniswapV3Pool {
12
    function initialize(uint160 sqrtPriceX96) external;
13
    function mint(address recipient, int24 tickLower, int24 tickUpper, uint128 amount, bytes calldata data)
14
        external
15
        returns (uint256 amount0, uint256 amount1);
16
    function burn(int24 tickLower, int24 tickUpper, uint128 amount)
17
        external
18
        returns (uint256 amount0, uint256 amount1);
19
    function swap(
20
        address recipient,
21
        bool zeroForOne,
22
        int256 amountSpecified,
23
        uint160 sqrtPriceLimitX96,
24
        bytes calldata data
25
    ) external returns (int256 amount0, int256 amount1);
26
}
27

                            
                        
28
interface IUniswapV3MintCallback {
29
    function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata data) external;
30
}
31

                            
                        
32
interface IUniswapV3SwapCallback {
33
    function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external;
34
}
35

                            
                        
36
abstract contract V3Helper is Test {
37
    IUniswapV3Factory v3Factory;
38

                            
                        
39
    function setUp() public virtual {
40
        address deployedAddr;
41
        bytes memory bytecode = vm.readFileBinary("test/bin/v3Factory.bytecode");
42
        assembly {
43
            deployedAddr := create(0, add(bytecode, 0x20), mload(bytecode))
44
        }
45
        v3Factory = IUniswapV3Factory(deployedAddr);
46
    }
47
}
48